capybara-mechanize 0.3.0 → 0.4.0.rc1

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/README.mdown CHANGED
@@ -49,7 +49,6 @@ Then you are ready to run the test like so
49
49
 
50
50
  Todo
51
51
  ----
52
- * Make the last 12 failing remote session spec pass, see remote_mechanize_spec and uncomment one line there to see them fail
53
52
  * Test this driver with non-rack/non-ruby projects
54
53
 
55
54
  Note on Patches/Pull Requests
@@ -1,5 +1,7 @@
1
1
  require 'capybara/rack_test/driver'
2
2
  require 'mechanize'
3
+ require 'capybara/mechanize/node'
4
+ require 'capybara/mechanize/form'
3
5
 
4
6
  class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
5
7
  extend Forwardable
@@ -28,104 +30,22 @@ class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
28
30
  last_request_remote? ? remote_response : super
29
31
  end
30
32
 
31
- def follow_redirects!
32
- 5.times do
33
- follow_redirect! if last_response.redirect?
34
- end
35
- raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if last_response.redirect?
36
- end
37
-
38
- def follow_redirect!
39
- unless last_response.redirect?
40
- raise "Last response was not a redirect. Cannot follow_redirect!"
41
- end
42
-
43
- get(last_location_header)
44
- end
45
-
46
- def process(method, path, *options)
47
- reset_cache!
48
- send(method, path, *options)
49
- follow_redirects!
50
- end
51
-
52
- def process_without_redirect(method, path, attributes, headers)
53
- path = @last_path if path.nil? || path.empty?
54
-
55
- if remote?(path)
56
- process_remote_request(method, path, attributes, headers)
57
- else
58
- register_local_request
59
-
60
- path = determine_path(path)
61
-
62
- reset_cache!
63
- send("racktest_#{method}", path, attributes, env.merge(headers))
64
- end
65
-
66
- @last_path = path
67
- end
68
-
69
- # TODO path Capybara to move this into its own method
70
- def determine_path(path)
71
- new_uri = URI.parse(path)
72
- current_uri = URI.parse(current_url)
73
-
74
- if new_uri.host
75
- @current_host = new_uri.scheme + '://' + new_uri.host
76
- end
77
-
78
- if new_uri.relative?
79
- path = request_path + path if path.start_with?('?')
33
+ # For each of these http methods, we want to intercept the method call.
34
+ # Then we determine if the call is remote or local.
35
+ # Remote: Handle it with our process_remote_request method.
36
+ # Local: Register the local request and call super to let RackTest get it.
37
+ [:get, :post, :put, :delete].each do |method|
38
+ define_method(method) do |path, params = {}, env = {}, &block|
39
+ path = @last_path if path.nil? || path.empty?
80
40
 
81
- unless path.start_with?('/')
82
- folders = request_path.split('/')
83
- if folders.empty?
84
- path = '/' + path
85
- else
86
- path = (folders[0, folders.size - 1] << path).join('/')
87
- end
41
+ if remote?(path)
42
+ process_remote_request(method, path, params, env, &block)
43
+ else
44
+ register_local_request
45
+ super(path, params, env, &block)
88
46
  end
89
- path = current_host + path
90
- end
91
- path
92
- end
93
-
94
- alias :racktest_get :get
95
- def get(path, attributes = {}, headers = {})
96
- process_without_redirect(:get, path, attributes, headers)
97
- end
98
47
 
99
- alias :racktest_post :post
100
- def post(path, attributes = {}, headers = {})
101
- process_without_redirect(:post, path, post_data(attributes), headers)
102
- end
103
-
104
- alias :racktest_put :put
105
- def put(path, attributes = {}, headers = {})
106
- process_without_redirect(:put, path, attributes, headers)
107
- end
108
-
109
- alias :racktest_delete :delete
110
- def delete(path, attributes = {}, headers = {})
111
- process_without_redirect(:delete, path, attributes, headers)
112
- end
113
-
114
- def post_data(params)
115
- params.inject({}) do |memo, param|
116
- case param
117
- when Hash
118
- param.each {|attribute, value| memo[attribute] = value }
119
- memo
120
- when Array
121
- case param.last
122
- when Hash
123
- param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
124
- else
125
- memo[param.first] = param.last
126
- end
127
- memo
128
- end
48
+ @last_path = path
129
49
  end
130
50
  end
131
51
 
@@ -143,14 +63,14 @@ class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
143
63
  end
144
64
  end
145
65
 
66
+ def find(selector)
67
+ dom.xpath(selector).map { |node| Capybara::Mechanize::Node.new(self, node) }
68
+ end
69
+
146
70
  attr_reader :agent
147
71
 
148
72
  private
149
73
 
150
- def last_location_header
151
- last_request_remote? ? remote_response.page.response['Location'] : last_response['Location']
152
- end
153
-
154
74
  def last_request_remote?
155
75
  !!@last_request_remote
156
76
  end
@@ -160,19 +80,38 @@ class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
160
80
  @last_request_remote = false
161
81
  end
162
82
 
83
+ def remote_request_path
84
+ @last_remote_uri.nil? ? nil : @last_remote_uri.path
85
+ end
86
+
87
+ def request_path
88
+ last_request_remote? ? remote_request_path : super
89
+ end
90
+
163
91
  def process_remote_request(method, url, attributes, headers)
164
92
  if remote?(url)
165
93
  uri = URI.parse(url)
166
- uri = resolve_relative_url(url) if uri.host.nil?
167
94
  @last_remote_uri = uri
168
95
  url = uri.to_s
169
96
 
170
97
  reset_cache!
171
98
  begin
172
- args = []
173
- args << attributes unless attributes.empty?
174
- args << headers unless headers.empty?
175
- @agent.send(method, url, *args)
99
+ if method == :post
100
+ if attributes.is_a? Mechanize::Form
101
+ submit_mechanize_form(url, attributes, headers)
102
+ else
103
+ @agent.send(method, url, attributes, headers)
104
+ end
105
+ elsif method == :get
106
+ if attributes.is_a? Mechanize::Form
107
+ submit_mechanize_form(url, attributes, headers)
108
+ else
109
+ referer = headers['HTTP_REFERER']
110
+ @agent.send(method, url, attributes, referer, headers)
111
+ end
112
+ else
113
+ @agent.send(method, url, attributes, headers)
114
+ end
176
115
  rescue => e
177
116
  raise "Received the following error for a #{method.to_s.upcase} request to #{url}: '#{e.message}'"
178
117
  end
@@ -180,40 +119,11 @@ class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
180
119
  end
181
120
  end
182
121
 
183
- # paths are combined "intelligently" as close as they would be by the browser, but still interpreting
184
- # routes from rails like "/user/login" as relative to a host including a possible subdirectory:
185
- # eg: app_host = localhost/mysite/ url = / result = http://localhost/mysite/
186
- # eg: app_host = localhost/mysite/ url = /home result = http://localhost/mysite/home
187
- # eg: app_host = localhost/mysite/ url = /user/login result = http://localhost/mysite/user/login
188
- # eg: app_host = localhost/mysite/ url = /mysite/login result = http://localhost/mysite/login
189
- # **** notice that 'mysite' is not repeated! *****
190
- def resolve_relative_url(url)
191
- if @last_remote_uri
192
- base_uri = @last_remote_uri
193
- path_prefix = ''
194
- else
195
- host = Capybara.app_host || Capybara.default_host
196
- # do this in text so we don't get the host interpretted as the scheme.
197
- host = "http://#{host}" unless host =~ %r{^https?://.*}
198
- base_uri = URI.parse(host)
199
- base_uri.path = '/' if base_uri.path.nil? || base_uri.path.empty?
200
- if base_uri.path.length > 1
201
- path_prefix = base_uri.path
202
- path_prefix += '/' unless path_prefix.end_with?('/') || url.start_with?('/')
203
-
204
- # if the prefix is already in the path, don't let it be there twice.
205
- if url.start_with?(path_prefix)
206
- path_prefix = ''
207
- end
208
- else
209
- path_prefix = ''
210
- end
211
- end
212
- uri = URI.parse(path_prefix + url)
213
- result_uri = base_uri.merge uri
122
+ def submit_mechanize_form(url, form, headers)
123
+ form.action = url
124
+ @agent.submit(form, nil, headers)
214
125
  end
215
126
 
216
-
217
127
  def remote_response
218
128
  ResponseProxy.new(@agent.current_page) if @agent.current_page
219
129
  end
@@ -244,6 +154,10 @@ class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
244
154
  headers
245
155
  end
246
156
 
157
+ def [](key)
158
+ headers[key]
159
+ end
160
+
247
161
  def status
248
162
  page.code.to_i
249
163
  end
@@ -2,12 +2,10 @@ require 'capybara/mechanize/browser'
2
2
 
3
3
  class Capybara::Mechanize::Driver < Capybara::RackTest::Driver
4
4
 
5
- def initialize(app = nil, options = {})
6
- if !app && !Capybara.app_host
7
- raise ArgumentError, "You have to set at least Capybara.app_host or Capybara.app"
8
- end
5
+ def initialize(app, options = {})
6
+ raise ArgumentError, "mechanize requires a rack application, but none was given" unless app
9
7
 
10
- @app, @options = app, options
8
+ super
11
9
  end
12
10
 
13
11
  def remote?(url)
@@ -0,0 +1,65 @@
1
+ class Capybara::Mechanize::Form < Capybara::RackTest::Form
2
+
3
+ def params(button)
4
+ if !use_mechanize?
5
+ return super
6
+ end
7
+
8
+ node = {}
9
+ # Create a fake form
10
+ class << node
11
+ def search(*args); []; end
12
+ end
13
+ node['method'] = method.to_s.upcase
14
+
15
+ if self.multipart?
16
+ node['enctype'] = 'multipart/form-data'
17
+ else
18
+ node['enctype'] = 'application/x-www-form-urlencoded'
19
+ end
20
+
21
+ @m_form = Mechanize::Form.new(node, nil, form_referer)
22
+
23
+ super
24
+
25
+ @m_form
26
+ end
27
+
28
+ private
29
+
30
+ def merge_param!(params, key, value)
31
+ if !use_mechanize?
32
+ return super
33
+ end
34
+
35
+ if value.is_a? NilUploadedFile
36
+ # Adding a nil value here will result in the form element existing with the empty string as its value.
37
+ # Instead don't add the form element at all.
38
+ return params
39
+ end
40
+
41
+ if value.is_a? Rack::Test::UploadedFile
42
+ @m_form.enctype = 'multipart/form-data'
43
+
44
+ ul = Mechanize::Form::FileUpload.new({'name' => key.to_s}, value.original_filename)
45
+ ul.mime_type = value.content_type
46
+ ul.file_data = (value.rewind; value.read)
47
+
48
+ @m_form.file_uploads << ul
49
+
50
+ return params
51
+ end
52
+
53
+ @m_form.fields << Mechanize::Form::Field.new({'name' => key.to_s}, value)
54
+
55
+ params
56
+ end
57
+
58
+ def use_mechanize?
59
+ driver.remote?(native['action'].to_s)
60
+ end
61
+
62
+ def form_referer
63
+ Mechanize::Page.new URI(driver.current_url)
64
+ end
65
+ end
@@ -0,0 +1,10 @@
1
+ class Capybara::Mechanize::Node < Capybara::RackTest::Node
2
+ def click
3
+ if tag_name == 'a'
4
+ super
5
+ elsif (tag_name == 'input' and %w(submit image).include?(type)) or
6
+ ((tag_name == 'button') and type.nil? or type == "submit")
7
+ Capybara::Mechanize::Form.new(driver, form).submit(self)
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Mechanize
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0.rc1'
4
4
  end
5
5
  end
@@ -2,9 +2,10 @@ 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
+ disable :protection
5
6
 
6
7
  get %r{/redirect_to/(.*)} do
7
- redirect params[:captures]
8
+ redirect params[:captures].first
8
9
  end
9
10
 
10
11
  get '/form_with_relative_action_to_host' do
@@ -35,10 +36,6 @@ class ExtendedTestApp < TestApp#< Sinatra::Base
35
36
  current_request_info
36
37
  end
37
38
 
38
- get '/host' do
39
- "Current host is #{request.scheme}://#{request.host}:#{request.port}"
40
- end
41
-
42
39
  get '/subsite/relative_link_to_host' do
43
40
  %{<a href="/subsite/request_info2/host">host</a>}
44
41
  end
@@ -54,11 +51,23 @@ class ExtendedTestApp < TestApp#< Sinatra::Base
54
51
  get '/redirect_with_http_param' do
55
52
  redirect '/redirect_target?foo=http'
56
53
  end
57
-
54
+
58
55
  get '/redirect_target' do
59
56
  %{correct redirect}
60
57
  end
61
58
 
59
+ get %r{/form_posts_to/(.*)} do
60
+ %{
61
+ <form action="#{params[:captures].first}" method="post">
62
+ <input type="submit" value="submit" />
63
+ </form>
64
+ }
65
+ end
66
+
67
+ post '/get_referer' do
68
+ request.referer.nil? ? "No referer" : "Got referer: #{request.referer}"
69
+ end
70
+
62
71
  private
63
72
 
64
73
  def current_request_info
@@ -1,151 +1,215 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Capybara::Driver::Mechanize, in local model" do
4
- before do
5
- @driver = Capybara::Mechanize::Driver.new(ExtendedTestApp)
3
+ describe Capybara::Mechanize::Driver, 'local' do
4
+ let(:driver) { Capybara::Mechanize::Driver.new(ExtendedTestApp) }
5
+
6
+ describe ':headers option' do
7
+ it 'should always set headers' do
8
+ driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
9
+ driver.visit('/get_header')
10
+ driver.html.should include('foobar')
11
+ end
12
+
13
+ it 'should keep headers on link clicks' do
14
+ driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
15
+ driver.visit('/header_links')
16
+ driver.find('.//a').first.click
17
+ driver.html.should include('foobar')
18
+ end
19
+
20
+ it 'should keep headers on form submit' do
21
+ driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
22
+ driver.visit('/header_links')
23
+ driver.find('.//input').first.click
24
+ driver.html.should include('foobar')
25
+ end
26
+
27
+ it 'should keep headers on redirects' do
28
+ driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
29
+ driver.visit('/get_header_via_redirect')
30
+ driver.html.should include('foobar')
31
+ end
32
+ end
33
+
34
+ describe ':follow_redirects option' do
35
+ it "defaults to following redirects" do
36
+ driver = Capybara::RackTest::Driver.new(TestApp)
37
+
38
+ driver.visit('/redirect')
39
+ driver.response.header['Location'].should be_nil
40
+ driver.browser.current_url.should match %r{/landed$}
41
+ end
42
+
43
+ it "is possible to not follow redirects" do
44
+ driver = Capybara::RackTest::Driver.new(TestApp, :follow_redirects => false)
45
+
46
+ driver.visit('/redirect')
47
+ driver.response.header['Location'].should match %r{/redirect_again$}
48
+ driver.browser.current_url.should match %r{/redirect$}
49
+ end
6
50
  end
7
-
8
- it "should throw an error when no rack app is given without an app host" do
9
- running do
10
- Capybara::Mechanize::Driver.new
11
- end.should raise_error(ArgumentError, "You have to set at least Capybara.app_host or Capybara.app")
51
+
52
+ describe ':redirect_limit option' do
53
+ context "with default redirect limit" do
54
+ let(:driver) { Capybara::RackTest::Driver.new(TestApp) }
55
+
56
+ it "should follow 5 redirects" do
57
+ driver.visit("/redirect/5/times")
58
+ driver.html.should include('redirection complete')
59
+ end
60
+
61
+ it "should not follow more than 6 redirects" do
62
+ expect do
63
+ driver.visit("/redirect/6/times")
64
+ end.to raise_error(Capybara::InfiniteRedirectError)
65
+ end
66
+ end
67
+
68
+ context "with 21 redirect limit" do
69
+ let(:driver) { Capybara::RackTest::Driver.new(TestApp, :redirect_limit => 21) }
70
+
71
+ it "should follow 21 redirects" do
72
+ driver.visit("/redirect/21/times")
73
+ driver.html.should include('redirection complete')
74
+ end
75
+
76
+ it "should not follow more than 21 redirects" do
77
+ expect do
78
+ driver.visit("/redirect/22/times")
79
+ end.to raise_error(Capybara::InfiniteRedirectError)
80
+ end
81
+ end
12
82
  end
13
-
14
- it_should_behave_like "driver"
15
- it_should_behave_like "driver with header support"
16
- it_should_behave_like "driver with status code support"
17
- it_should_behave_like "driver with cookies support"
18
- it_should_behave_like "driver with infinite redirect detection"
19
83
 
20
84
  it "should default to local mode for relative paths" do
21
- @driver.should_not be_remote('/')
85
+ driver.should_not be_remote('/')
22
86
  end
23
-
87
+
24
88
  it "should default to local mode for the default host" do
25
- @driver.should_not be_remote('http://www.example.com')
89
+ driver.should_not be_remote('http://www.example.com')
26
90
  end
27
91
 
28
92
  context "with an app_host" do
29
-
93
+
30
94
  before do
31
95
  Capybara.app_host = 'http://www.remote.com'
32
96
  end
33
-
97
+
34
98
  after do
35
99
  Capybara.app_host = nil
36
100
  end
37
101
 
38
102
  it "should treat urls as remote" do
39
- @driver.should be_remote('http://www.remote.com')
103
+ driver.should be_remote('http://www.remote.com')
40
104
  end
41
105
  end
42
106
 
43
107
  context "with a default url, no app host" do
44
- before :each do
108
+ before do
45
109
  Capybara.default_host = 'www.local.com'
46
110
  end
47
-
111
+
48
112
  it "should allow local hosts to be set" do
49
113
  Capybara::Mechanize.local_hosts = ['subdomain.local.com']
50
- @driver.should_not be_remote('http://subdomain.local.com')
114
+ driver.should_not be_remote('http://subdomain.local.com')
51
115
  end
52
-
116
+
53
117
  it "should treat urls with the same host names as local" do
54
- @driver.should_not be_remote('http://www.local.com')
118
+ driver.should_not be_remote('http://www.local.com')
55
119
  end
56
-
120
+
57
121
  it "should treat other urls as remote" do
58
- @driver.should be_remote('http://www.remote.com')
122
+ driver.should be_remote('http://www.remote.com')
59
123
  end
60
-
124
+
61
125
  it "should treat relative paths as remote if the previous request was remote" do
62
- @driver.visit(REMOTE_TEST_URL)
63
- @driver.should be_remote('/some_relative_link')
126
+ driver.visit(REMOTE_TEST_URL)
127
+ driver.should be_remote('/some_relative_link')
64
128
  end
65
129
 
66
130
  it "should treat relative paths as local if the previous request was local" do
67
- @driver.visit('http://www.local.com')
68
- @driver.should_not be_remote('/some_relative_link')
131
+ driver.visit('http://www.local.com')
132
+ driver.should_not be_remote('/some_relative_link')
69
133
  end
70
134
 
71
135
  it "should receive the right host" do
72
- @driver.visit('http://www.local.com/host')
136
+ driver.visit('http://www.local.com/host')
73
137
  should_be_a_local_get
74
138
  end
75
139
 
76
140
  it "should consider relative paths to be local when the previous request was local" do
77
- @driver.visit('http://www.local.com/host')
78
- @driver.visit('/host')
141
+ driver.visit('http://www.local.com/host')
142
+ driver.visit('/host')
79
143
 
80
144
  should_be_a_local_get
81
- @driver.should_not be_remote('/first_local')
145
+ driver.should_not be_remote('/first_local')
82
146
  end
83
-
147
+
84
148
  it "should consider relative paths to be remote when the previous request was remote" do
85
- @driver.visit("#{REMOTE_TEST_URL}/host")
86
- @driver.get('/host')
149
+ driver.visit("#{REMOTE_TEST_URL}/host")
150
+ driver.get('/host')
87
151
 
88
152
  should_be_a_remote_get
89
- @driver.should be_remote('/second_remote')
153
+ driver.should be_remote('/second_remote')
90
154
  end
91
-
155
+
92
156
  it "should always switch to the right context" do
93
- @driver.visit('http://www.local.com/host')
94
- @driver.get('/host')
95
- @driver.get("#{REMOTE_TEST_URL}/host")
96
- @driver.get('/host')
97
- @driver.get('http://www.local.com/host')
157
+ driver.visit('http://www.local.com/host')
158
+ driver.get('/host')
159
+ driver.get("#{REMOTE_TEST_URL}/host")
160
+ driver.get('/host')
161
+ driver.get('http://www.local.com/host')
98
162
 
99
163
  should_be_a_local_get
100
- @driver.should_not be_remote('/second_local')
164
+ driver.should_not be_remote('/second_local')
101
165
  end
102
166
 
103
167
  it "should follow redirects from local to remote" do
104
- @driver.visit("http://www.local.com/redirect_to/#{REMOTE_TEST_URL}/host")
168
+ driver.visit("http://www.local.com/redirect_to/#{REMOTE_TEST_URL}/host")
105
169
  should_be_a_remote_get
106
170
  end
107
-
171
+
108
172
  it "should follow redirects from remote to local" do
109
- @driver.visit("#{REMOTE_TEST_URL}/redirect_to/http://www.local.com/host")
173
+ driver.visit("#{REMOTE_TEST_URL}/redirect_to/http://www.local.com/host")
110
174
  should_be_a_local_get
111
175
  end
112
-
113
- after :each do
176
+
177
+ after do
114
178
  Capybara.default_host = nil
115
179
  end
116
-
180
+
117
181
  it "should raise a useful error for sites that return a 404, because it is probably a misconfiguration" do
118
- lambda {
119
- @driver.visit("http://iamreallysurethatthisdoesntexist.com/canttouchthis")
120
- }.should raise_error(%r{Received the following error for a GET request to http://iamreallysurethatthisdoesntexist.com/canttouchthis:})
182
+ expect {
183
+ driver.visit("http://iamreallysurethatthisdoesntexist.com/canttouchthis")
184
+ }.to raise_error(%r{Received the following error for a GET request to http://iamreallysurethatthisdoesntexist.com/canttouchthis:})
121
185
  end
122
186
  end
123
187
 
124
188
  it "should include the right host when remote" do
125
- @driver.visit("#{REMOTE_TEST_URL}/host")
189
+ driver.visit("#{REMOTE_TEST_URL}/host")
126
190
  should_be_a_remote_get
127
191
  end
128
192
 
129
193
  describe '#reset!' do
130
- before :each do
194
+ before do
131
195
  Capybara.default_host = 'http://www.local.com'
132
196
  end
133
197
 
134
198
  it 'should reset remote host' do
135
- @driver.visit("#{REMOTE_TEST_URL}/host")
199
+ driver.visit("#{REMOTE_TEST_URL}/host")
136
200
  should_be_a_remote_get
137
- @driver.reset!
138
- @driver.visit("/host")
201
+ driver.reset!
202
+ driver.visit("/host")
139
203
  should_be_a_local_get
140
204
  end
141
205
  end
142
206
 
143
207
  def should_be_a_remote_get
144
- @driver.body.should include(REMOTE_TEST_URL)
208
+ driver.current_url.should include(REMOTE_TEST_URL)
145
209
  end
146
-
210
+
147
211
  def should_be_a_local_get
148
- @driver.body.should include("www.local.com")
212
+ driver.current_url.should include("www.local.com")
149
213
  end
150
-
214
+ #
151
215
  end
@@ -1,65 +1,46 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Capybara::Mechanize::Driver do
4
- before(:each) do
3
+ describe Capybara::Mechanize::Driver, 'remote' do
4
+ before do
5
5
  Capybara.app_host = REMOTE_TEST_URL
6
6
  end
7
-
8
- after(:each) do
7
+
8
+ after do
9
9
  Capybara.app_host = nil
10
10
  end
11
11
 
12
- before do
13
- @driver = Capybara::Mechanize::Driver.new
14
- end
15
-
12
+ let(:driver) { Capybara::Mechanize::Driver.new(ExtendedTestApp) }
13
+
16
14
  context "in remote mode" do
17
- it "should not throw an error when no rack app is given" do
18
- running do
19
- Capybara::Mechanize::Driver.new
20
- end.should_not raise_error(ArgumentError)
21
- end
22
-
23
15
  it "should pass arguments through to a get request" do
24
- @driver.visit("#{REMOTE_TEST_URL}/form/get", {:form => "success"})
25
- @driver.body.should include('success')
16
+ driver.visit("#{REMOTE_TEST_URL}/form/get", {:form => "success"})
17
+ driver.html.should include('success')
26
18
  end
27
19
 
28
20
  it "should pass arguments through to a post request" do
29
- @driver.post("#{REMOTE_TEST_URL}/form", {:form => "success"})
30
- @driver.body.should include('success')
21
+ driver.post("#{REMOTE_TEST_URL}/form", {:form => "success"})
22
+ driver.html.should include('success')
31
23
  end
32
24
 
33
- context "for a post request" do
34
-
35
- it "should transform nested map in post data" do
36
- @driver.post("#{REMOTE_TEST_URL}/form", {:form => {:key => "value"}})
37
- @driver.body.should include('key: value')
25
+ describe "redirect" do
26
+ it "should handle redirects with http-params" do
27
+ driver.visit "#{REMOTE_TEST_URL}/redirect_with_http_param"
28
+ driver.html.should include('correct redirect')
38
29
  end
39
-
40
30
  end
41
31
 
42
- context "process remote request" do
43
-
44
- it "should transform nested map in post data" do
45
- @driver.submit(:post, "#{REMOTE_TEST_URL}/form", {:form => {:key => "value"}})
46
- @driver.body.should include('key: value')
32
+ context "for a post request" do
33
+ it 'transforms nested map in post data' do
34
+ driver.post("#{REMOTE_TEST_URL}/form", {:form => {:key => 'value'}})
35
+ driver.html.should include(':key=>"value"')
47
36
  end
48
-
49
37
  end
50
38
 
51
- describe "redirect" do
52
- it "should handle redirects with http-params" do
53
- @driver.visit "#{REMOTE_TEST_URL}/redirect_with_http_param"
54
- @driver.body.should include('correct redirect')
39
+ context 'process remote request' do
40
+ it 'transforms nested map in post data' do
41
+ driver.submit(:post, "#{REMOTE_TEST_URL}/form", {:form => {:key => 'value'}})
42
+ driver.html.should include(':key=>"value"')
55
43
  end
56
44
  end
57
-
58
- it_should_behave_like "driver"
59
- it_should_behave_like "driver with header support"
60
- it_should_behave_like "driver with status code support"
61
- it_should_behave_like "driver with cookies support"
62
- it_should_behave_like "driver with infinite redirect detection"
63
45
  end
64
-
65
46
  end
@@ -1,59 +1,103 @@
1
1
  require 'spec_helper'
2
2
 
3
+ module TestSessions
4
+ Mechanize = Capybara::Session.new(:mechanize, TestApp)
5
+ end
6
+
7
+ Capybara::SpecHelper.run_specs TestSessions::Mechanize, "Mechanize", :skip => [
8
+ :js,
9
+ :screenshot,
10
+ :frames,
11
+ :windows,
12
+ :server
13
+ ]
14
+
3
15
  describe Capybara::Session do
4
16
  context 'with mechanize driver' do
17
+ let(:session) { Capybara::Session.new(:mechanize, ExtendedTestApp) }
18
+
5
19
  before do
6
- @session = Capybara::Session.new(:mechanize, TestApp)
7
- @session.driver.options[:respect_data_method] = true
8
20
  Capybara.default_host = 'http://www.local.com'
9
21
  end
10
22
 
11
23
  describe '#driver' do
12
24
  it "should be a mechanize driver" do
13
- @session.driver.should be_an_instance_of(Capybara::Mechanize::Driver)
25
+ session.driver.should be_an_instance_of(Capybara::Mechanize::Driver)
14
26
  end
15
27
  end
16
28
 
17
29
  describe '#mode' do
18
30
  it "should remember the mode" do
19
- @session.mode.should == :mechanize
31
+ session.mode.should == :mechanize
20
32
  end
21
33
  end
22
34
 
23
35
  describe '#click_link' do
24
- it "should use data-method if available" do
25
- @session.visit "/with_html"
26
- @session.click_link "A link with data-method"
27
- @session.body.should include('The requested object was deleted')
36
+ it "should use data-method if option is true" do
37
+ session.driver.options[:respect_data_method] = true
38
+ session.visit "/with_html"
39
+ session.click_link "A link with data-method"
40
+ session.html.should include('The requested object was deleted')
41
+ end
42
+
43
+ it "should not use data-method if option is false" do
44
+ session.driver.options[:respect_data_method] = false
45
+ session.visit "/with_html"
46
+ session.click_link "A link with data-method"
47
+ session.html.should include('Not deleted')
48
+ end
49
+
50
+ it "should use data-method if available even if it's capitalized" do
51
+ session.driver.options[:respect_data_method] = true
52
+ session.visit "/with_html"
53
+ session.click_link "A link with capitalized data-method"
54
+ session.html.should include('The requested object was deleted')
55
+ end
56
+
57
+ after do
58
+ session.driver.options[:respect_data_method] = false
59
+ end
60
+ end
61
+
62
+ describe "#attach_file" do
63
+ context "with multipart form" do
64
+ it "should submit an empty form-data section if no file is submitted" do
65
+ session.visit("/form")
66
+ session.click_button("Upload Empty")
67
+ session.html.should include('Successfully ignored empty file field.')
68
+ end
28
69
  end
29
70
  end
30
71
 
31
72
  it "should use the last remote url when following relative links" do
32
- @session.visit("#{REMOTE_TEST_URL}/relative_link_to_host")
33
- @session.click_link "host"
34
- @session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method get")
73
+ session.visit("#{REMOTE_TEST_URL}/relative_link_to_host")
74
+ session.click_link "host"
75
+ session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method get")
35
76
  end
36
77
 
37
78
  it "should use the last remote url when submitting a form with a relative action" do
38
- @session.visit("#{REMOTE_TEST_URL}/form_with_relative_action_to_host")
39
- @session.click_button "submit"
40
- @session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method post")
79
+ session.visit("#{REMOTE_TEST_URL}/form_with_relative_action_to_host")
80
+ session.click_button "submit"
81
+ session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method post")
41
82
  end
42
83
 
43
84
  it "should use the last url when submitting a form with no action" do
44
- @session.visit("#{REMOTE_TEST_URL}/request_info/form_with_no_action")
45
- @session.click_button "submit"
46
- @session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/form_with_no_action, method post")
85
+ session.visit("#{REMOTE_TEST_URL}/request_info/form_with_no_action")
86
+ session.click_button "submit"
87
+ session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/form_with_no_action, method post")
47
88
  end
48
89
 
49
90
  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")
91
+ session.visit("#{REMOTE_TEST_URL}/request_info/user_agent")
92
+ 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
93
  end
53
94
 
54
- it_should_behave_like "session"
55
- it_should_behave_like "session without javascript support"
56
- it_should_behave_like "session with headers support"
57
- it_should_behave_like "session with status code support"
95
+ context 'form referer when switching from local to remote' do
96
+ it 'sends the referer' do
97
+ session.visit "/form_posts_to/#{REMOTE_TEST_URL}/get_referer"
98
+ session.click_button 'submit'
99
+ session.body.should include 'Got referer'
100
+ end
101
+ end
58
102
  end
59
103
  end
@@ -1,66 +1,102 @@
1
1
  require 'spec_helper'
2
2
 
3
+ module TestSessions
4
+ Mechanize = Capybara::Session.new(:mechanize, TestApp)
5
+ end
6
+
7
+ shared_context "remote tests" do
8
+ before do
9
+ Capybara.app_host = REMOTE_TEST_URL
10
+ end
11
+
12
+ after do
13
+ Capybara.app_host = nil
14
+ end
15
+ end
16
+
17
+ session_describe = Capybara::SpecHelper.run_specs TestSessions::Mechanize, "Mechanize", :skip => [
18
+ :js,
19
+ :screenshot,
20
+ :frames,
21
+ :windows,
22
+ :server
23
+ ]
24
+
25
+ session_describe.include_context("remote tests")
26
+
27
+ disabler = DisableExternalTests.new
28
+ disabler.tests_to_disable = [
29
+ ['#visit', 'when Capybara.always_include_port is true', 'should fetch a response from the driver with an absolute url without a port'],
30
+ ['#reset_session!', 'raises any errors caught inside the server']
31
+ ]
32
+ disabler.disable(session_describe)
33
+
3
34
  describe Capybara::Session do
4
35
  context 'with remote mechanize driver' do
5
- before(:each) do
6
- Capybara.app_host = REMOTE_TEST_URL
7
- end
36
+ include_context 'remote tests'
8
37
 
9
- after(:each) do
10
- Capybara.app_host = nil
11
- end
12
-
13
-
14
- before do
15
- @session = Capybara::Session.new(:mechanize)
16
- @session.driver.options[:respect_data_method] = true
17
- end
38
+ let(:session) { Capybara::Session.new(:mechanize, ExtendedTestApp) }
18
39
 
19
40
  describe '#driver' do
20
41
  it "should be a mechanize driver" do
21
- @session.driver.should be_an_instance_of(Capybara::Mechanize::Driver)
42
+ session.driver.should be_an_instance_of(Capybara::Mechanize::Driver)
22
43
  end
23
44
  end
24
45
 
25
46
  describe '#mode' do
26
47
  it "should remember the mode" do
27
- @session.mode.should == :mechanize
48
+ session.mode.should == :mechanize
28
49
  end
29
50
  end
30
51
 
31
52
  describe '#click_link' do
32
- it "should use data-method if available" do
33
- @session.visit "/with_html"
34
- @session.click_link "A link with data-method"
35
- @session.body.should include('The requested object was deleted')
53
+ it "should use data-method if option is true" do
54
+ session.driver.options[:respect_data_method] = true
55
+ session.visit "/with_html"
56
+ session.click_link "A link with data-method"
57
+ session.html.should include('The requested object was deleted')
36
58
  end
37
- end
38
-
39
-
40
59
 
41
- # Pending: Still 16 failing tests here (result is 706 examples, 16 failures, instead of 385 examples)
42
- # it_should_behave_like "session"
60
+ it "should not use data-method if option is false" do
61
+ session.driver.options[:respect_data_method] = false
62
+ session.visit "/with_html"
63
+ session.click_link "A link with data-method"
64
+ session.html.should include('Not deleted')
65
+ end
43
66
 
44
- it_should_behave_like "session without javascript support"
45
- it_should_behave_like "session with headers support"
46
- it_should_behave_like "session with status code support"
67
+ it "should use data-method if available even if it's capitalized" do
68
+ session.driver.options[:respect_data_method] = true
69
+ session.visit "/with_html"
70
+ session.click_link "A link with capitalized data-method"
71
+ session.html.should include('The requested object was deleted')
72
+ end
47
73
 
74
+ after do
75
+ session.driver.options[:respect_data_method] = false
76
+ end
77
+ end
48
78
 
49
- context "remote app in a sub-domain" do
50
- before :each do
51
- Capybara.app_host = "#{REMOTE_TEST_URL}/subsite"
79
+ describe "#attach_file" do
80
+ context "with multipart form" do
81
+ it "should submit an empty form-data section if no file is submitted" do
82
+ session.visit("/form")
83
+ session.click_button("Upload Empty")
84
+ session.html.should include('Successfully ignored empty file field.')
85
+ end
52
86
  end
87
+ end
53
88
 
89
+ context "remote app in a sub-path" do
54
90
  it "follows relative link correctly" do
55
- @session.visit "/relative_link_to_host"
56
- @session.click_link "host"
57
- @session.body.should include('request_info2/host')
91
+ session.visit "/subsite/relative_link_to_host"
92
+ session.click_link "host"
93
+ session.body.should include('request_info2/host')
58
94
  end
59
95
 
60
96
  it "follows local link correctly" do
61
- @session.visit "/local_link_to_host"
62
- @session.click_link "host"
63
- @session.body.should include('request_info2/host')
97
+ session.visit "/subsite/local_link_to_host"
98
+ session.click_link "host"
99
+ session.body.should include('request_info2/host')
64
100
  end
65
101
  end
66
102
  end
data/spec/spec_helper.rb CHANGED
@@ -1,47 +1,28 @@
1
- require 'bundler/setup'
2
- require 'capybara'
3
- require 'capybara/dsl'
1
+ require 'capybara/spec/spec_helper'
4
2
  require 'capybara/mechanize'
5
3
  require 'capybara/spec/extended_test_app'
6
4
 
7
- require 'sinatra'
5
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
8
6
 
9
- # TODO move this stuff into capybara
10
- require 'capybara/spec/driver'
11
- require 'capybara/spec/session'
7
+ $LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
12
8
 
13
- alias :running :lambda
9
+ Dir[File.join(PROJECT_ROOT, 'spec', 'support', '**', '*.rb')].each { |file| require(file) }
14
10
 
15
- Capybara.default_wait_time = 0 # less timeout so tests run faster
16
- Capybara.app = ExtendedTestApp
11
+ RSpec.configure do |config|
12
+ # Spruce up the focus!
13
+ config.filter_run :focus => true
14
+ config.run_all_when_everything_filtered = true
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
17
16
 
18
- rack_server = Capybara::Server.new(Capybara.app)
19
- rack_server.boot
17
+ # Used with DisableExternalTests
18
+ config.filter_run_excluding :external_test_disabled
20
19
 
21
- RSpec.configure do |config|
22
20
  config.after do
23
- Capybara.default_selector = :xpath
24
21
  Capybara::Mechanize.local_hosts = nil
25
22
  end
26
- # config.filter_run :focus => true
27
- end
28
-
29
- REMOTE_TEST_URL = "http://localhost:#{rack_server.port}"
30
23
 
31
-
32
-
33
- # for testing private methods, courtesy of
34
- # http://kailuowang.blogspot.com.au/2010/08/testing-private-methods-in-rspec.html
35
- def describe_internally *args, &block
36
- example = describe *args, &block
37
- klass = args[0]
38
- if klass.is_a? Class
39
- saved_private_instance_methods = klass.private_instance_methods
40
- example.before do
41
- klass.class_eval { public *saved_private_instance_methods }
42
- end
43
- example.after do
44
- klass.class_eval { private *saved_private_instance_methods }
45
- end
46
- end
24
+ Capybara::SpecHelper.configure(config)
47
25
  end
26
+
27
+ setup = ExtendedTestAppSetup.new.boot
28
+ REMOTE_TEST_URL = setup.remote_test_url
@@ -0,0 +1,20 @@
1
+ class DisableExternalTests
2
+ attr_accessor :tests_to_disable
3
+
4
+ def disable(top_level_example_group)
5
+ tests_to_disable.each do |to_disable|
6
+ example_group = top_level_example_group
7
+
8
+ example_description = to_disable.pop
9
+
10
+ to_disable.each do |description|
11
+ example_group = example_group.children.find{ |g| g.description == description }
12
+ end
13
+
14
+ example = example_group.examples.find{ |e| e.description == example_description }
15
+
16
+ example.metadata[:external_test_disabled] = true
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # This class works around some weirdness with Capybara's test suite and sinatra's behavior.
2
+ # We need to make sure that sinatra uses TestApp for at least one request before the Capybara session
3
+ # specs run. Without this we get errors from sinatra trying to handle requests with TestApp.clone
4
+ class ExtendedTestAppSetup
5
+ include Capybara::DSL
6
+
7
+ attr_reader :remote_test_url
8
+
9
+ def boot
10
+ boot_test_app
11
+ boot_remote_app
12
+
13
+ self
14
+ end
15
+
16
+ def boot_test_app
17
+ Capybara.app = TestApp
18
+ dummy_server = Capybara::Server.new(TestApp)
19
+ dummy_server.boot
20
+
21
+ # Boot TestApp's Sinatra
22
+ visit '/'
23
+ end
24
+
25
+ def boot_remote_app
26
+ remote_server = Capybara::Server.new(ExtendedTestApp)
27
+ remote_server.boot
28
+ @remote_test_url = "http://localhost:#{remote_server.port}"
29
+ end
30
+ end
metadata CHANGED
@@ -1,38 +1,54 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-mechanize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
5
- prerelease:
4
+ version: 0.4.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jeroen van Dijk
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-14 00:00:00.000000000Z
12
+ date: 2013-02-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mechanize
16
- requirement: &70180442685720 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '2.3'
21
+ version: '2.5'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70180442685720
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.5'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: capybara
27
- requirement: &70180442685240 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
31
36
  - !ruby/object:Gem::Version
32
- version: '1.1'
37
+ version: '2.0'
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.1
33
41
  type: :runtime
34
42
  prerelease: false
35
- version_requirements: *70180442685240
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '2.0'
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: 2.0.1
36
52
  description: RackTest driver for Capybara, but with remote request support thanks
37
53
  to mechanize
38
54
  email: jeroen@jeevidee.nl
@@ -43,15 +59,18 @@ files:
43
59
  - lib/capybara/mechanize/browser.rb
44
60
  - lib/capybara/mechanize/cucumber.rb
45
61
  - lib/capybara/mechanize/driver.rb
62
+ - lib/capybara/mechanize/form.rb
63
+ - lib/capybara/mechanize/node.rb
46
64
  - lib/capybara/mechanize/version.rb
47
65
  - lib/capybara/mechanize.rb
48
66
  - lib/capybara/spec/extended_test_app.rb
49
67
  - spec/driver/mechanize_driver_spec.rb
50
68
  - spec/driver/remote_mechanize_driver_spec.rb
51
- - spec/relative_urls_spec.rb
52
69
  - spec/session/mechanize_spec.rb
53
70
  - spec/session/remote_mechanize_spec.rb
54
71
  - spec/spec_helper.rb
72
+ - spec/support/disable_external_tests.rb
73
+ - spec/support/extended_test_app_setup.rb
55
74
  - README.mdown
56
75
  homepage: https://github.com/jeroenvandijk/capybara-mechanize
57
76
  licenses: []
@@ -74,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
93
  version: '0'
75
94
  requirements: []
76
95
  rubyforge_project:
77
- rubygems_version: 1.8.15
96
+ rubygems_version: 1.8.24
78
97
  signing_key:
79
98
  specification_version: 3
80
99
  summary: RackTest driver for Capybara with remote request support
@@ -1,68 +0,0 @@
1
- require "rspec"
2
- require 'capybara'
3
- require 'capybara/mechanize/browser'
4
- require File.expand_path('../spec_helper.rb', __FILE__)
5
-
6
- describe_internally Capybara::Mechanize::Browser do
7
- describe "Resolving Relative URLs" do
8
-
9
- before(:all) do
10
- @original_app_host = Capybara.app_host
11
- @driver = Object.new
12
- @browser = Capybara::Mechanize::Browser.new(@driver)
13
- end
14
-
15
- after(:all) do
16
- Capybara.app_host = @original_app_host
17
- @browser.reset_host!
18
- end
19
-
20
- context "resolving on 'http://localhost'" do
21
- before(:all) do
22
- Capybara.app_host ='http://localhost'
23
- end
24
-
25
- it "resolves '/'" do
26
- @browser.resolve_relative_url('/').to_s.should == 'http://localhost/'
27
- end
28
-
29
- it "resolves '/home'" do
30
- @browser.resolve_relative_url('/home').to_s.should == 'http://localhost/home'
31
- end
32
-
33
- it "resolves 'home'" do
34
- @browser.resolve_relative_url('home').to_s.should == 'http://localhost/home'
35
- end
36
-
37
- it "resolves 'user/login'" do
38
- @browser.resolve_relative_url('user/login').to_s.should == 'http://localhost/user/login'
39
- end
40
- end
41
-
42
- context "resolving on 'http://localhost/subsite'" do
43
- before() do
44
- Capybara.app_host='http://localhost/subsite'
45
- end
46
-
47
- it "resolves '/'" do
48
- @browser.resolve_relative_url('/').to_s.should == 'http://localhost/subsite/'
49
- end
50
-
51
- it "resolves '/home'" do
52
- @browser.resolve_relative_url('/home').to_s.should == 'http://localhost/subsite/home'
53
- end
54
-
55
- it "resolves 'home'" do
56
- @browser.resolve_relative_url('home').to_s.should == 'http://localhost/subsite/home'
57
- end
58
-
59
- it "resolves 'user/login'" do
60
- @browser.resolve_relative_url('user/login').to_s.should == 'http://localhost/subsite/user/login'
61
- end
62
-
63
- it "resolves '/subsite/user/login'" do
64
- @browser.resolve_relative_url('/subsite/user/login').to_s.should == 'http://localhost/subsite/user/login'
65
- end
66
- end
67
- end
68
- end