mechanize 1.0.1.beta.20110107104205 → 2.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mechanize might be problematic. Click here for more details.
- data.tar.gz.sig +2 -0
- data/{lib/mechanize/chain/post_connect_hook.rb → .gemtest} +0 -0
- data/CHANGELOG.rdoc +51 -6
- data/EXAMPLES.rdoc +5 -3
- data/GUIDE.rdoc +72 -32
- data/LICENSE.rdoc +20 -340
- data/Manifest.txt +20 -27
- data/README.rdoc +12 -9
- data/Rakefile +5 -2
- data/examples/spider.rb +13 -2
- data/lib/mechanize.rb +545 -267
- data/lib/mechanize/content_type_error.rb +1 -1
- data/lib/mechanize/cookie.rb +72 -65
- data/lib/mechanize/cookie_jar.rb +197 -148
- data/lib/mechanize/element_matcher.rb +35 -0
- data/lib/mechanize/file.rb +3 -1
- data/lib/mechanize/file_connection.rb +17 -0
- data/lib/mechanize/file_request.rb +26 -0
- data/lib/mechanize/file_response.rb +61 -47
- data/lib/mechanize/form.rb +57 -58
- data/lib/mechanize/form/image_button.rb +2 -3
- data/lib/mechanize/form/multi_select_list.rb +71 -55
- data/lib/mechanize/form/select_list.rb +34 -62
- data/lib/mechanize/monkey_patch.rb +13 -11
- data/lib/mechanize/page.rb +277 -270
- data/lib/mechanize/page/image.rb +6 -2
- data/lib/mechanize/redirect_limit_reached_error.rb +1 -1
- data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -1
- data/lib/mechanize/response_code_error.rb +3 -3
- data/lib/mechanize/unsupported_scheme_error.rb +1 -1
- data/lib/mechanize/uri_resolver.rb +82 -0
- data/lib/mechanize/util.rb +76 -60
- data/test/helper.rb +35 -5
- data/test/htdocs/dir with spaces/foo.html +1 -0
- data/test/htdocs/rails_3_encoding_hack_form_test.html +27 -0
- data/test/htdocs/tc_base_images.html +10 -0
- data/test/htdocs/tc_images.html +8 -0
- data/test/htdocs/test_click.html +11 -0
- data/test/servlets.rb +3 -2
- data/test/test_authenticate.rb +5 -5
- data/test/test_errors.rb +8 -8
- data/test/test_follow_meta.rb +4 -4
- data/test/test_form_as_hash.rb +4 -4
- data/test/test_forms.rb +3 -7
- data/test/test_hash_api.rb +2 -2
- data/test/test_headers.rb +1 -1
- data/test/test_images.rb +19 -0
- data/test/test_mech.rb +6 -6
- data/test/test_mechanize.rb +687 -0
- data/test/{test_cookie_class.rb → test_mechanize_cookie.rb} +52 -45
- data/test/test_mechanize_cookie_jar.rb +400 -0
- data/test/test_mechanize_file.rb +7 -1
- data/test/test_mechanize_file_request.rb +19 -0
- data/test/test_mechanize_file_response.rb +21 -0
- data/test/test_mechanize_form_image_button.rb +12 -0
- data/test/test_mechanize_page.rb +165 -0
- data/test/test_mechanize_uri_resolver.rb +29 -0
- data/test/{test_util.rb → test_mechanize_util.rb} +1 -1
- data/test/test_multi_select.rb +12 -0
- data/test/test_post_form.rb +7 -0
- data/test/test_redirect_verb_handling.rb +6 -6
- data/test/test_scheme.rb +0 -7
- data/test/test_verbs.rb +3 -3
- metadata +106 -72
- metadata.gz.sig +0 -0
- data/lib/mechanize/chain.rb +0 -36
- data/lib/mechanize/chain/auth_headers.rb +0 -78
- data/lib/mechanize/chain/body_decoding_handler.rb +0 -50
- data/lib/mechanize/chain/connection_resolver.rb +0 -28
- data/lib/mechanize/chain/custom_headers.rb +0 -21
- data/lib/mechanize/chain/handler.rb +0 -9
- data/lib/mechanize/chain/header_resolver.rb +0 -48
- data/lib/mechanize/chain/parameter_resolver.rb +0 -22
- data/lib/mechanize/chain/pre_connect_hook.rb +0 -20
- data/lib/mechanize/chain/request_resolver.rb +0 -31
- data/lib/mechanize/chain/response_body_parser.rb +0 -36
- data/lib/mechanize/chain/response_header_handler.rb +0 -34
- data/lib/mechanize/chain/response_reader.rb +0 -39
- data/lib/mechanize/chain/ssl_resolver.rb +0 -40
- data/lib/mechanize/chain/uri_resolver.rb +0 -75
- data/test/chain/test_argument_validator.rb +0 -14
- data/test/chain/test_auth_headers.rb +0 -25
- data/test/chain/test_custom_headers.rb +0 -18
- data/test/chain/test_header_resolver.rb +0 -27
- data/test/chain/test_parameter_resolver.rb +0 -35
- data/test/chain/test_request_resolver.rb +0 -29
- data/test/chain/test_response_reader.rb +0 -24
- data/test/test_cookie_jar.rb +0 -324
- data/test/test_page.rb +0 -124
data/test/test_authenticate.rb
CHANGED
@@ -20,9 +20,9 @@ class BasicAuthTest < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
def test_no_duplicate_headers
|
22
22
|
block_called = false
|
23
|
-
@agent.pre_connect_hooks << lambda { |
|
23
|
+
@agent.pre_connect_hooks << lambda { |_, request|
|
24
24
|
block_called = true
|
25
|
-
|
25
|
+
request.to_hash.each do |k,v|
|
26
26
|
assert_equal(1, v.length)
|
27
27
|
end
|
28
28
|
}
|
@@ -35,10 +35,10 @@ class BasicAuthTest < Test::Unit::TestCase
|
|
35
35
|
class << @agent
|
36
36
|
alias :old_fetch_page :fetch_page
|
37
37
|
attr_accessor :requests
|
38
|
-
def fetch_page(args)
|
38
|
+
def fetch_page(uri, method, *args)
|
39
39
|
@requests ||= []
|
40
|
-
x = old_fetch_page(args)
|
41
|
-
@requests <<
|
40
|
+
x = old_fetch_page(uri, method, *args)
|
41
|
+
@requests << method
|
42
42
|
x
|
43
43
|
end
|
44
44
|
end
|
data/test/test_errors.rb
CHANGED
@@ -7,9 +7,9 @@ class MechErrorsTest < Test::Unit::TestCase
|
|
7
7
|
|
8
8
|
def test_bad_form_method
|
9
9
|
page = @agent.get("http://localhost/bad_form_test.html")
|
10
|
-
assert_raise
|
10
|
+
assert_raise ArgumentError do
|
11
11
|
@agent.submit(page.forms.first)
|
12
|
-
|
12
|
+
end
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_non_exist
|
@@ -24,21 +24,21 @@ class MechErrorsTest < Test::Unit::TestCase
|
|
24
24
|
page = @agent.get("http://localhost/form_test.html")
|
25
25
|
form = page.form_with(:name => 'post_form1')
|
26
26
|
form.radiobuttons.each { |r| r.checked = true }
|
27
|
-
assert_raise
|
27
|
+
assert_raise Mechanize::Error do
|
28
28
|
@agent.submit(form)
|
29
|
-
|
29
|
+
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_unknown_agent
|
33
|
-
assert_raise
|
33
|
+
assert_raise ArgumentError do
|
34
34
|
@agent.user_agent_alias = "Aaron's Browser"
|
35
|
-
|
35
|
+
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_bad_url
|
39
|
-
assert_raise
|
39
|
+
assert_raise ArgumentError do
|
40
40
|
@agent.get('/foo.html')
|
41
|
-
|
41
|
+
end
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_unsupported_scheme
|
data/test/test_follow_meta.rb
CHANGED
@@ -8,8 +8,8 @@ class FollowMetaTest < Test::Unit::TestCase
|
|
8
8
|
def test_dont_follow_meta_in_body
|
9
9
|
@agent.follow_meta_refresh = true
|
10
10
|
requests = []
|
11
|
-
@agent.pre_connect_hooks << lambda { |
|
12
|
-
requests <<
|
11
|
+
@agent.pre_connect_hooks << lambda { |_, request|
|
12
|
+
requests << request
|
13
13
|
}
|
14
14
|
|
15
15
|
@agent.get('http://localhost/tc_meta_in_body.html')
|
@@ -25,8 +25,8 @@ class FollowMetaTest < Test::Unit::TestCase
|
|
25
25
|
def test_meta_refresh_does_not_send_referer
|
26
26
|
@agent.follow_meta_refresh = true
|
27
27
|
requests = []
|
28
|
-
@agent.pre_connect_hooks << lambda { |
|
29
|
-
requests <<
|
28
|
+
@agent.pre_connect_hooks << lambda { |_, request|
|
29
|
+
requests << request
|
30
30
|
}
|
31
31
|
|
32
32
|
@agent.get('http://localhost/tc_follow_meta.html')
|
data/test/test_form_as_hash.rb
CHANGED
@@ -46,13 +46,13 @@ class TestFormHash < Test::Unit::TestCase
|
|
46
46
|
form = @page.forms.first
|
47
47
|
|
48
48
|
assert_not_nil(form)
|
49
|
-
|
50
|
-
|
49
|
+
assert(!form.has_field?('name'))
|
50
|
+
assert(!form.has_value?('Aaron'))
|
51
51
|
assert_equal(0, form.keys.length)
|
52
52
|
assert_equal(0, form.values.length)
|
53
53
|
form['name'] = 'Aaron'
|
54
|
-
|
55
|
-
|
54
|
+
assert(form.has_field?('name'))
|
55
|
+
assert(form.has_value?('Aaron'))
|
56
56
|
assert_equal(1, form.keys.length)
|
57
57
|
assert_equal(['name'], form.keys)
|
58
58
|
assert_equal(1, form.values.length)
|
data/test/test_forms.rb
CHANGED
@@ -271,7 +271,7 @@ class FormsMechTest < Test::Unit::TestCase
|
|
271
271
|
page = @agent.submit(get_form, get_form.buttons.first)
|
272
272
|
|
273
273
|
# Check that the submitted fields exist
|
274
|
-
assert_equal(
|
274
|
+
assert_equal(6, page.links.size, "Not enough links")
|
275
275
|
assert_not_nil(
|
276
276
|
page.links.find { |l| l.text == "likes ham:on" },
|
277
277
|
"likes ham check box missing"
|
@@ -296,10 +296,6 @@ class FormsMechTest < Test::Unit::TestCase
|
|
296
296
|
page.links.find { |l| l.text == "button.x:9" },
|
297
297
|
"Image button missing"
|
298
298
|
)
|
299
|
-
assert_not_nil(
|
300
|
-
page.links.find { |l| l.text == "button:button" },
|
301
|
-
"Image button missing"
|
302
|
-
)
|
303
299
|
end
|
304
300
|
|
305
301
|
def test_post_with_space_in_action
|
@@ -572,10 +568,10 @@ class FormsMechTest < Test::Unit::TestCase
|
|
572
568
|
form = page.form_with(:name => 'post_form')
|
573
569
|
|
574
570
|
assert_not_nil(form)
|
575
|
-
|
571
|
+
assert(!form.has_field?('intarweb'))
|
576
572
|
f = form.add_field!('intarweb')
|
577
573
|
assert_not_nil(f)
|
578
|
-
|
574
|
+
assert(form.has_field?('intarweb'))
|
579
575
|
end
|
580
576
|
|
581
577
|
def test_field_error
|
data/test/test_hash_api.rb
CHANGED
@@ -26,8 +26,8 @@ class TestHashApi < Test::Unit::TestCase
|
|
26
26
|
|
27
27
|
def test_get_with_referer
|
28
28
|
request = nil
|
29
|
-
@agent.pre_connect_hooks << lambda { |
|
30
|
-
request =
|
29
|
+
@agent.pre_connect_hooks << lambda { |_, req|
|
30
|
+
request = req
|
31
31
|
}
|
32
32
|
|
33
33
|
@agent.get( :url => 'http://localhost/',
|
data/test/test_headers.rb
CHANGED
data/test/test_images.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class ImagesMechTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@agent = Mechanize.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_base
|
9
|
+
page = @agent.get("http://google.com/tc_base_images.html")
|
10
|
+
assert_equal page.images[0].url, "http://localhost/a.jpg"
|
11
|
+
assert_equal page.images[1].url, "http://localhost/b.gif"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_base2
|
15
|
+
page = @agent.get("http://google.com/tc_images.html")
|
16
|
+
assert_equal page.images[0].url, "http://google.com/a.jpg"
|
17
|
+
assert_equal page.images[1].url, "http://google.com/b.gif"
|
18
|
+
end
|
19
|
+
end
|
data/test/test_mech.rb
CHANGED
@@ -40,8 +40,8 @@ class TestMechMethods < Test::Unit::TestCase
|
|
40
40
|
|
41
41
|
def test_get_no_referer
|
42
42
|
requests = []
|
43
|
-
@agent.pre_connect_hooks << lambda { |
|
44
|
-
requests <<
|
43
|
+
@agent.pre_connect_hooks << lambda { |_, request|
|
44
|
+
requests << request
|
45
45
|
}
|
46
46
|
|
47
47
|
@agent.get('http://localhost/')
|
@@ -59,8 +59,8 @@ class TestMechMethods < Test::Unit::TestCase
|
|
59
59
|
|
60
60
|
def test_post_connect_hook_gets_called
|
61
61
|
response = nil
|
62
|
-
@agent.post_connect_hooks << lambda { |
|
63
|
-
response =
|
62
|
+
@agent.post_connect_hooks << lambda { |_, res|
|
63
|
+
response = res
|
64
64
|
}
|
65
65
|
|
66
66
|
@agent.get('http://localhost/')
|
@@ -69,8 +69,8 @@ class TestMechMethods < Test::Unit::TestCase
|
|
69
69
|
|
70
70
|
def test_get_with_referer
|
71
71
|
request = nil
|
72
|
-
@agent.pre_connect_hooks << lambda { |
|
73
|
-
request =
|
72
|
+
@agent.pre_connect_hooks << lambda { |_, req|
|
73
|
+
request = req
|
74
74
|
}
|
75
75
|
|
76
76
|
@agent.get('http://localhost/', URI.parse('http://google.com/'))
|
@@ -0,0 +1,687 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class TestMechanize < Test::Unit::TestCase
|
6
|
+
|
7
|
+
KEY = OpenSSL::PKey::RSA.new 512
|
8
|
+
name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
|
9
|
+
CERT = OpenSSL::X509::Certificate.new
|
10
|
+
CERT.version = 2
|
11
|
+
CERT.serial = 0
|
12
|
+
CERT.not_before = Time.now
|
13
|
+
CERT.not_after = Time.now + 60
|
14
|
+
CERT.public_key = KEY.public_key
|
15
|
+
CERT.subject = name
|
16
|
+
CERT.issuer = name
|
17
|
+
CERT.sign KEY, OpenSSL::Digest::SHA1.new
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@agent = Mechanize.new
|
21
|
+
@uri = URI.parse 'http://example/'
|
22
|
+
@req = Net::HTTP::Get.new '/'
|
23
|
+
|
24
|
+
@res = Net::HTTPOK.allocate
|
25
|
+
@res.instance_variable_set :@code, 200
|
26
|
+
@res.instance_variable_set :@header, {}
|
27
|
+
|
28
|
+
@headers = if RUBY_VERSION > '1.9' then
|
29
|
+
%w[accept user-agent]
|
30
|
+
else
|
31
|
+
%w[accept]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_cert_key_file
|
36
|
+
Tempfile.open 'key' do |key|
|
37
|
+
Tempfile.open 'cert' do |cert|
|
38
|
+
key.write KEY.to_pem
|
39
|
+
key.rewind
|
40
|
+
|
41
|
+
cert.write CERT.to_pem
|
42
|
+
cert.rewind
|
43
|
+
|
44
|
+
agent = Mechanize.new do |a|
|
45
|
+
a.cert = cert.path
|
46
|
+
a.key = key.path
|
47
|
+
end
|
48
|
+
|
49
|
+
# Certificate#== seems broken
|
50
|
+
assert_equal CERT.to_pem, agent.http.certificate.to_pem
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_cert_key_object
|
56
|
+
agent = Mechanize.new do |a|
|
57
|
+
a.cert = CERT
|
58
|
+
a.key = KEY
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_equal CERT, agent.http.certificate
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_connection_for_file
|
65
|
+
uri = URI.parse 'file:///nonexistent'
|
66
|
+
conn = @agent.connection_for uri
|
67
|
+
|
68
|
+
assert_equal Mechanize::FileConnection.new, conn
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_connection_for_http
|
72
|
+
conn = @agent.connection_for @uri
|
73
|
+
|
74
|
+
assert_equal @agent.http, conn
|
75
|
+
end
|
76
|
+
|
77
|
+
#def test_download
|
78
|
+
# Dir.mktmpdir do |dir|
|
79
|
+
# file = "#{dir}/download"
|
80
|
+
# open file, 'w' do |io|
|
81
|
+
# @agent.download 'http://example', io
|
82
|
+
# end
|
83
|
+
|
84
|
+
# assert_equal 1, File.stat(file).size
|
85
|
+
# end
|
86
|
+
#end
|
87
|
+
|
88
|
+
def test_enable_gzip
|
89
|
+
@agent.enable_gzip @req
|
90
|
+
|
91
|
+
assert_equal 'gzip,deflate,identity', @req['accept-encoding']
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_enable_gzip_no
|
95
|
+
@agent.gzip_enabled = false
|
96
|
+
|
97
|
+
@agent.enable_gzip @req
|
98
|
+
|
99
|
+
assert_equal 'identity', @req['accept-encoding']
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_fetch_page_file_plus
|
103
|
+
Tempfile.open '++plus++' do |io|
|
104
|
+
content = 'plusses +++'
|
105
|
+
io.write content
|
106
|
+
io.rewind
|
107
|
+
|
108
|
+
uri = URI.parse "file://#{Mechanize::Util.uri_escape io.path}"
|
109
|
+
|
110
|
+
page = @agent.send :fetch_page, uri
|
111
|
+
|
112
|
+
assert_equal content, page.body
|
113
|
+
assert_kind_of Mechanize::File, page
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_fetch_page_file_space
|
118
|
+
foo = File.expand_path("../htdocs/dir with spaces/foo.html", __FILE__)
|
119
|
+
|
120
|
+
uri = URI.parse "file://#{Mechanize::Util.uri_escape foo}"
|
121
|
+
|
122
|
+
page = @agent.send :fetch_page, uri
|
123
|
+
|
124
|
+
assert_equal File.read(foo), page.body
|
125
|
+
assert_kind_of Mechanize::Page, page
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_fetch_page_file_nonexistent
|
129
|
+
uri = URI.parse 'file:///nonexistent'
|
130
|
+
|
131
|
+
e = assert_raises Mechanize::ResponseCodeError do
|
132
|
+
page = @agent.send :fetch_page, uri
|
133
|
+
end
|
134
|
+
|
135
|
+
assert_equal '404 => Net::HTTPNotFound', e.message
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_get_yield
|
139
|
+
pages = nil
|
140
|
+
|
141
|
+
@agent.get("http://localhost/file_upload.html") { |page|
|
142
|
+
pages = page
|
143
|
+
}
|
144
|
+
|
145
|
+
assert pages
|
146
|
+
assert_equal('File Upload Form', pages.title)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_http_request_file
|
150
|
+
uri = URI.parse 'file:///nonexistent'
|
151
|
+
request = @agent.http_request uri, :get
|
152
|
+
|
153
|
+
assert_kind_of Mechanize::FileRequest, request
|
154
|
+
assert_equal '/nonexistent', request.path
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_http_request_get
|
158
|
+
request = @agent.http_request @uri, :get
|
159
|
+
|
160
|
+
assert_kind_of Net::HTTP::Get, request
|
161
|
+
assert_equal '/', request.path
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_http_request_post
|
165
|
+
request = @agent.http_request @uri, :post
|
166
|
+
|
167
|
+
assert_kind_of Net::HTTP::Post, request
|
168
|
+
assert_equal '/', request.path
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_post_connect
|
172
|
+
@agent.post_connect_hooks << proc { |agent, response|
|
173
|
+
assert_equal @agent, agent
|
174
|
+
assert_kind_of Net::HTTPResponse, response
|
175
|
+
throw :called
|
176
|
+
}
|
177
|
+
|
178
|
+
assert_throws :called do
|
179
|
+
@agent.post_connect @res
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_pre_connect
|
184
|
+
@agent.pre_connect_hooks << proc { |agent, request|
|
185
|
+
assert_equal @agent, agent
|
186
|
+
assert_kind_of Net::HTTPRequest, request
|
187
|
+
throw :called
|
188
|
+
}
|
189
|
+
|
190
|
+
assert_throws :called do
|
191
|
+
@agent.pre_connect @req
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_request_cookies
|
196
|
+
uri = URI.parse 'http://host.example.com'
|
197
|
+
Mechanize::Cookie.parse uri, 'hello=world domain=.example.com' do |cookie|
|
198
|
+
@agent.cookie_jar.add uri, cookie
|
199
|
+
end
|
200
|
+
|
201
|
+
@agent.request_cookies @req, uri
|
202
|
+
|
203
|
+
assert_equal 'hello=world domain=.example.com', @req['Cookie']
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_request_cookies_none
|
207
|
+
@agent.request_cookies @req, @uri
|
208
|
+
|
209
|
+
assert_nil @req['Cookie']
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_request_cookies_many
|
213
|
+
uri = URI.parse 'http://host.example.com'
|
214
|
+
cookie_str = 'a=b domain=.example.com, c=d domain=.example.com'
|
215
|
+
Mechanize::Cookie.parse uri, cookie_str do |cookie|
|
216
|
+
@agent.cookie_jar.add uri, cookie
|
217
|
+
end
|
218
|
+
|
219
|
+
@agent.request_cookies @req, uri
|
220
|
+
|
221
|
+
expected = cookie_str.sub ', ', '; '
|
222
|
+
|
223
|
+
assert_equal expected, @req['Cookie']
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_request_cookies_wrong_domain
|
227
|
+
uri = URI.parse 'http://host.example.com'
|
228
|
+
Mechanize::Cookie.parse uri, 'hello=world domain=.example.com' do |cookie|
|
229
|
+
@agent.cookie_jar.add uri, cookie
|
230
|
+
end
|
231
|
+
|
232
|
+
@agent.request_cookies @req, @uri
|
233
|
+
|
234
|
+
assert_nil @req['Cookie']
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_request_host
|
238
|
+
@agent.request_host @req, @uri
|
239
|
+
|
240
|
+
assert_equal 'example', @req['host']
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_request_host_nonstandard
|
244
|
+
@uri.port = 81
|
245
|
+
|
246
|
+
@agent.request_host @req, @uri
|
247
|
+
|
248
|
+
assert_equal 'example:81', @req['host']
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_request_language_charset
|
252
|
+
@agent.request_language_charset @req
|
253
|
+
|
254
|
+
assert_equal 'en-us,en;q=0.5', @req['accept-language']
|
255
|
+
assert_equal 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', @req['accept-charset']
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_request_add_headers
|
259
|
+
@agent.request_add_headers @req, 'Content-Length' => 300
|
260
|
+
|
261
|
+
assert_equal '300', @req['content-length']
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_request_add_headers_etag
|
265
|
+
@agent.request_add_headers @req, :etag => '300'
|
266
|
+
|
267
|
+
assert_equal '300', @req['etag']
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_request_add_headers_if_modified_since
|
271
|
+
@agent.request_add_headers @req, :if_modified_since => 'some_date'
|
272
|
+
|
273
|
+
assert_equal 'some_date', @req['if-modified-since']
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_request_add_headers_none
|
277
|
+
@agent.request_add_headers @req
|
278
|
+
|
279
|
+
assert_equal @headers, @req.to_hash.keys.sort
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_request_add_headers_request_headers
|
283
|
+
@agent.request_headers['X-Foo'] = 'bar'
|
284
|
+
|
285
|
+
@agent.request_add_headers @req
|
286
|
+
|
287
|
+
assert_equal @headers + %w[x-foo], @req.to_hash.keys.sort
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_request_add_headers_symbol
|
291
|
+
e = assert_raises ArgumentError do
|
292
|
+
@agent.request_add_headers @req, :content_length => 300
|
293
|
+
end
|
294
|
+
|
295
|
+
assert_equal 'unknown header symbol content_length', e.message
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_request_referer
|
299
|
+
referer = URI.parse 'http://old.example'
|
300
|
+
|
301
|
+
@agent.request_referer @req, @uri, referer
|
302
|
+
|
303
|
+
assert_equal 'http://old.example', @req['referer']
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_request_referer_https
|
307
|
+
uri = URI.parse 'https://example'
|
308
|
+
referer = URI.parse 'https://old.example'
|
309
|
+
|
310
|
+
@agent.request_referer @req, uri, referer
|
311
|
+
|
312
|
+
assert_equal 'https://old.example', @req['referer']
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_request_referer_https_downgrade
|
316
|
+
referer = URI.parse 'https://old.example'
|
317
|
+
|
318
|
+
@agent.request_referer @req, @uri, referer
|
319
|
+
|
320
|
+
assert_nil @req['referer']
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_request_referer_https_downgrade_case
|
324
|
+
uri = URI.parse 'http://example'
|
325
|
+
referer = URI.parse 'httpS://old.example'
|
326
|
+
|
327
|
+
@agent.request_referer @req, uri, referer
|
328
|
+
|
329
|
+
assert_nil @req['referer']
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_request_referer_none
|
333
|
+
@agent.request_referer @req, @uri, nil
|
334
|
+
|
335
|
+
assert_nil @req['referer']
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_request_user_agent
|
339
|
+
@agent.request_user_agent @req
|
340
|
+
|
341
|
+
assert_match %r%^Mechanize/#{Mechanize::VERSION}%, @req['user-agent']
|
342
|
+
|
343
|
+
ruby_version = if RUBY_PATCHLEVEL >= 0 then
|
344
|
+
"#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}"
|
345
|
+
else
|
346
|
+
"#{RUBY_VERSION}dev#{RUBY_REVISION}"
|
347
|
+
end
|
348
|
+
|
349
|
+
assert_match %r%Ruby/#{ruby_version}%, @req['user-agent']
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_resolve_parameters_body
|
353
|
+
input_params = { :q => 'hello' }
|
354
|
+
|
355
|
+
uri, params = @agent.resolve_parameters @uri, :post, input_params
|
356
|
+
|
357
|
+
assert_equal 'http://example/', uri.to_s
|
358
|
+
assert_equal input_params, params
|
359
|
+
end
|
360
|
+
|
361
|
+
def test_resolve_parameters_query
|
362
|
+
uri, params = @agent.resolve_parameters @uri, :get, :q => 'hello'
|
363
|
+
|
364
|
+
assert_equal 'http://example/?q=hello', uri.to_s
|
365
|
+
assert_nil params
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_resolve_parameters_query_append
|
369
|
+
input_params = { :q => 'hello' }
|
370
|
+
@uri.query = 'a=b'
|
371
|
+
|
372
|
+
uri, params = @agent.resolve_parameters @uri, :get, input_params
|
373
|
+
|
374
|
+
assert_equal 'http://example/?a=b&q=hello', uri.to_s
|
375
|
+
assert_nil params
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_response_cookies
|
379
|
+
uri = URI.parse 'http://host.example.com'
|
380
|
+
cookie_str = 'a=b domain=.example.com'
|
381
|
+
@res.instance_variable_set(:@header,
|
382
|
+
'set-cookie' => [cookie_str],
|
383
|
+
'content-type' => %w[text/html])
|
384
|
+
page = Mechanize::Page.new uri, @res, '', 200, @agent
|
385
|
+
|
386
|
+
@agent.response_cookies @res, uri, page
|
387
|
+
|
388
|
+
assert_equal ['a=b domain=.example.com'],
|
389
|
+
@agent.cookie_jar.cookies(uri).map { |c| c.to_s }
|
390
|
+
end
|
391
|
+
|
392
|
+
def test_response_cookies_meta
|
393
|
+
uri = URI.parse 'http://host.example.com'
|
394
|
+
cookie_str = 'a=b domain=.example.com'
|
395
|
+
|
396
|
+
body = <<-BODY
|
397
|
+
<head>
|
398
|
+
<meta http-equiv="Set-Cookie" content="#{cookie_str}">
|
399
|
+
</head>"
|
400
|
+
BODY
|
401
|
+
|
402
|
+
@res.instance_variable_set(:@header,
|
403
|
+
'content-type' => %w[text/html])
|
404
|
+
page = Mechanize::Page.new uri, @res, body, 200, @agent
|
405
|
+
|
406
|
+
@agent.response_cookies @res, uri, page
|
407
|
+
|
408
|
+
assert_equal ['a=b domain=.example.com'],
|
409
|
+
@agent.cookie_jar.cookies(uri).map { |c| c.to_s }
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_response_follow_meta_refresh
|
413
|
+
uri = URI.parse 'http://example/#id+1'
|
414
|
+
|
415
|
+
body = <<-BODY
|
416
|
+
<title></title>
|
417
|
+
<meta http-equiv="refresh" content="0">
|
418
|
+
BODY
|
419
|
+
|
420
|
+
page = Mechanize::Page.new(uri, {'content-type' => 'text/html'}, body,
|
421
|
+
200, @agent)
|
422
|
+
|
423
|
+
@agent.follow_meta_refresh = true
|
424
|
+
|
425
|
+
page = @agent.response_follow_meta_refresh @res, uri, page, 0
|
426
|
+
|
427
|
+
assert_equal uri, page.uri
|
428
|
+
end
|
429
|
+
|
430
|
+
def test_response_read
|
431
|
+
def @res.read_body() yield 'part' end
|
432
|
+
def @res.content_length() 4 end
|
433
|
+
|
434
|
+
body = @agent.response_read @res, @req
|
435
|
+
|
436
|
+
assert_equal 'part', body
|
437
|
+
end
|
438
|
+
|
439
|
+
def test_response_read_content_length_head
|
440
|
+
req = Net::HTTP::Head.new '/'
|
441
|
+
|
442
|
+
def @res.content_length() end
|
443
|
+
def @res.read_body() end
|
444
|
+
|
445
|
+
body = @agent.response_read @res, req
|
446
|
+
|
447
|
+
assert_equal '', body
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_response_read_content_length_mismatch
|
451
|
+
def @res.content_length() 5 end
|
452
|
+
def @res.read_body() yield 'part' end
|
453
|
+
|
454
|
+
e = assert_raises EOFError do
|
455
|
+
@agent.response_read @res, @req
|
456
|
+
end
|
457
|
+
|
458
|
+
assert_equal 'Content-Length (5) does not match response body length (4)',
|
459
|
+
e.message
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_response_read_content_length_redirect
|
463
|
+
res = Net::HTTPFound.allocate
|
464
|
+
def res.content_length() 5 end
|
465
|
+
def res.code() 302 end
|
466
|
+
def res.read_body() yield 'part' end
|
467
|
+
res.instance_variable_set :@header, {}
|
468
|
+
|
469
|
+
body = @agent.response_read res, @req
|
470
|
+
|
471
|
+
assert_equal 'part', body
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_response_read_encoding_7_bit
|
475
|
+
def @res.read_body() yield 'part' end
|
476
|
+
def @res.content_length() 4 end
|
477
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[7bit]
|
478
|
+
|
479
|
+
body = @agent.response_read @res, @req
|
480
|
+
|
481
|
+
assert_equal 'part', body
|
482
|
+
end
|
483
|
+
|
484
|
+
def test_response_read_encoding_deflate
|
485
|
+
def @res.read_body()
|
486
|
+
yield "x\x9C+H,*\x01\x00\x04?\x01\xB8"
|
487
|
+
end
|
488
|
+
def @res.content_length() 12 end
|
489
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[deflate]
|
490
|
+
|
491
|
+
body = @agent.response_read @res, @req
|
492
|
+
|
493
|
+
assert_equal 'part', body
|
494
|
+
end
|
495
|
+
|
496
|
+
# IIS/6.0 ASP.NET/2.0.50727 does not wrap deflate with zlib, WTF?
|
497
|
+
def test_response_read_encoding_deflate_no_zlib
|
498
|
+
def @res.read_body()
|
499
|
+
yield "+H,*\001\000"
|
500
|
+
end
|
501
|
+
def @res.content_length() 6 end
|
502
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[deflate]
|
503
|
+
|
504
|
+
body = @agent.response_read @res, @req
|
505
|
+
|
506
|
+
assert_equal 'part', body
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_response_read_encoding_gzip
|
510
|
+
def @res.read_body()
|
511
|
+
yield "\037\213\b\0002\002\225M\000\003"
|
512
|
+
yield "+H,*\001\000\306p\017I\004\000\000\000"
|
513
|
+
end
|
514
|
+
def @res.content_length() 24 end
|
515
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[gzip]
|
516
|
+
|
517
|
+
body = @agent.response_read @res, @req
|
518
|
+
|
519
|
+
assert_equal 'part', body
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_response_read_encoding_none
|
523
|
+
def @res.read_body() yield 'part' end
|
524
|
+
def @res.content_length() 4 end
|
525
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[none]
|
526
|
+
|
527
|
+
body = @agent.response_read @res, @req
|
528
|
+
|
529
|
+
assert_equal 'part', body
|
530
|
+
end
|
531
|
+
|
532
|
+
def test_response_read_encoding_x_gzip
|
533
|
+
def @res.read_body()
|
534
|
+
yield "\037\213\b\0002\002\225M\000\003"
|
535
|
+
yield "+H,*\001\000\306p\017I\004\000\000\000"
|
536
|
+
end
|
537
|
+
def @res.content_length() 24 end
|
538
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[x-gzip]
|
539
|
+
|
540
|
+
body = @agent.response_read @res, @req
|
541
|
+
|
542
|
+
assert_equal 'part', body
|
543
|
+
end
|
544
|
+
|
545
|
+
def test_response_read_encoding_unknown
|
546
|
+
def @res.read_body() yield 'part' end
|
547
|
+
def @res.content_length() 4 end
|
548
|
+
@res.instance_variable_set :@header, 'content-encoding' => %w[unknown]
|
549
|
+
|
550
|
+
e = assert_raises Mechanize::Error do
|
551
|
+
@agent.response_read @res, @req
|
552
|
+
end
|
553
|
+
|
554
|
+
assert_equal 'Unsupported Content-Encoding: unknown', e.message
|
555
|
+
end
|
556
|
+
|
557
|
+
def test_response_read_file
|
558
|
+
Tempfile.open 'pi.txt' do |tempfile|
|
559
|
+
tempfile.write "π\n"
|
560
|
+
tempfile.flush
|
561
|
+
tempfile.rewind
|
562
|
+
|
563
|
+
uri = URI.parse "file://#{tempfile.path}"
|
564
|
+
req = Mechanize::FileRequest.new uri
|
565
|
+
res = Mechanize::FileResponse.new tempfile.path
|
566
|
+
|
567
|
+
body = @agent.response_read res, req
|
568
|
+
|
569
|
+
expected = "π\n"
|
570
|
+
expected.force_encoding Encoding::BINARY if expected.respond_to? :encoding
|
571
|
+
|
572
|
+
assert_equal expected, body
|
573
|
+
assert_equal Encoding::BINARY, body.encoding if body.respond_to? :encoding
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_response_read_no_body
|
578
|
+
req = Net::HTTP::Options.new '/'
|
579
|
+
|
580
|
+
def @res.content_length() end
|
581
|
+
def @res.read_body() end
|
582
|
+
|
583
|
+
body = @agent.response_read @res, req
|
584
|
+
|
585
|
+
assert_equal '', body
|
586
|
+
end
|
587
|
+
|
588
|
+
def test_response_read_unknown_code
|
589
|
+
res = Net::HTTPUnknownResponse.allocate
|
590
|
+
res.instance_variable_set :@code, 9999
|
591
|
+
def res.read_body() yield 'part' end
|
592
|
+
|
593
|
+
e = assert_raises Mechanize::ResponseCodeError do
|
594
|
+
@agent.response_read res, @req
|
595
|
+
end
|
596
|
+
|
597
|
+
assert_equal res, e.page
|
598
|
+
end
|
599
|
+
|
600
|
+
def test_response_parse
|
601
|
+
body = '<title>hi</title>'
|
602
|
+
@res.instance_variable_set :@header, 'content-type' => %w[text/html]
|
603
|
+
|
604
|
+
page = @agent.response_parse @res, body, @uri
|
605
|
+
|
606
|
+
assert_instance_of Mechanize::Page, page
|
607
|
+
assert_equal @agent, page.mech
|
608
|
+
end
|
609
|
+
|
610
|
+
def test_response_parse_content_type_case
|
611
|
+
body = '<title>hi</title>'
|
612
|
+
@res.instance_variable_set(:@header, 'content-type' => %w[text/HTML])
|
613
|
+
|
614
|
+
page = @agent.response_parse @res, body, @uri
|
615
|
+
|
616
|
+
assert_instance_of Mechanize::Page, page
|
617
|
+
|
618
|
+
assert_equal 'text/HTML', page.content_type
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_response_parse_content_type_encoding
|
622
|
+
body = '<title>hi</title>'
|
623
|
+
@res.instance_variable_set(:@header,
|
624
|
+
'content-type' =>
|
625
|
+
%w[text/html;charset=ISO-8859-1])
|
626
|
+
|
627
|
+
page = @agent.response_parse @res, body, @uri
|
628
|
+
|
629
|
+
assert_instance_of Mechanize::Page, page
|
630
|
+
assert_equal @agent, page.mech
|
631
|
+
|
632
|
+
assert_equal 'ISO-8859-1', page.encoding
|
633
|
+
assert_equal 'ISO-8859-1', page.parser.encoding
|
634
|
+
end
|
635
|
+
|
636
|
+
def test_response_parse_content_type_encoding_garbage
|
637
|
+
body = '<title>hi</title>'
|
638
|
+
@res.instance_variable_set(:@header,
|
639
|
+
'content-type' =>
|
640
|
+
%w[text/html; charset=garbage_charset])
|
641
|
+
|
642
|
+
page = @agent.response_parse @res, body, @uri
|
643
|
+
|
644
|
+
assert_instance_of Mechanize::Page, page
|
645
|
+
assert_equal @agent, page.mech
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_response_parse_content_type_encoding_broken_iso_8859_1
|
649
|
+
body = '<title>hi</title>'
|
650
|
+
@res.instance_variable_set(:@header,
|
651
|
+
'content-type' =>
|
652
|
+
%w[text/html; charset=ISO_8859-1])
|
653
|
+
|
654
|
+
page = @agent.response_parse @res, body, @uri
|
655
|
+
|
656
|
+
assert_instance_of Mechanize::Page, page
|
657
|
+
assert_equal 'ISO_8859-1', page.encoding
|
658
|
+
end
|
659
|
+
|
660
|
+
def test_response_parse_content_type_encoding_broken_utf_8
|
661
|
+
body = '<title>hi</title>'
|
662
|
+
@res.instance_variable_set(:@header,
|
663
|
+
'content-type' =>
|
664
|
+
%w[text/html; charset=UTF8])
|
665
|
+
|
666
|
+
page = @agent.response_parse @res, body, @uri
|
667
|
+
|
668
|
+
assert_instance_of Mechanize::Page, page
|
669
|
+
assert_equal 'UTF8', page.encoding
|
670
|
+
assert_equal 'UTF8', page.parser.encoding
|
671
|
+
end
|
672
|
+
|
673
|
+
def test_response_parse_content_type_encoding_semicolon
|
674
|
+
body = '<title>hi</title>'
|
675
|
+
@res.instance_variable_set(:@header,
|
676
|
+
'content-type' =>
|
677
|
+
%w[text/html;charset=UTF-8;])
|
678
|
+
|
679
|
+
page = @agent.response_parse @res, body, @uri
|
680
|
+
|
681
|
+
assert_instance_of Mechanize::Page, page
|
682
|
+
|
683
|
+
assert_equal 'UTF-8', page.encoding
|
684
|
+
end
|
685
|
+
|
686
|
+
end
|
687
|
+
|