mechanize 2.7.4 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci-test.yml +45 -0
  3. data/.yardopts +8 -0
  4. data/{CHANGELOG.rdoc → CHANGELOG.md} +151 -86
  5. data/EXAMPLES.rdoc +1 -24
  6. data/Gemfile +1 -1
  7. data/{LICENSE.rdoc → LICENSE.txt} +4 -0
  8. data/README.md +77 -0
  9. data/Rakefile +18 -3
  10. data/examples/rubygems.rb +2 -2
  11. data/lib/mechanize.rb +3 -2
  12. data/lib/mechanize/chunked_termination_error.rb +1 -0
  13. data/lib/mechanize/content_type_error.rb +1 -0
  14. data/lib/mechanize/cookie.rb +1 -13
  15. data/lib/mechanize/cookie_jar.rb +4 -12
  16. data/lib/mechanize/directory_saver.rb +1 -0
  17. data/lib/mechanize/download.rb +2 -1
  18. data/lib/mechanize/element_matcher.rb +5 -1
  19. data/lib/mechanize/element_not_found_error.rb +1 -0
  20. data/lib/mechanize/file.rb +2 -1
  21. data/lib/mechanize/file_connection.rb +5 -3
  22. data/lib/mechanize/file_request.rb +1 -0
  23. data/lib/mechanize/file_response.rb +4 -1
  24. data/lib/mechanize/file_saver.rb +1 -0
  25. data/lib/mechanize/form.rb +112 -45
  26. data/lib/mechanize/form/button.rb +1 -0
  27. data/lib/mechanize/form/check_box.rb +1 -0
  28. data/lib/mechanize/form/field.rb +47 -0
  29. data/lib/mechanize/form/file_upload.rb +1 -0
  30. data/lib/mechanize/form/hidden.rb +1 -0
  31. data/lib/mechanize/form/image_button.rb +1 -0
  32. data/lib/mechanize/form/keygen.rb +1 -0
  33. data/lib/mechanize/form/multi_select_list.rb +8 -14
  34. data/lib/mechanize/form/option.rb +3 -1
  35. data/lib/mechanize/form/radio_button.rb +1 -0
  36. data/lib/mechanize/form/reset.rb +1 -0
  37. data/lib/mechanize/form/select_list.rb +1 -0
  38. data/lib/mechanize/form/submit.rb +1 -0
  39. data/lib/mechanize/form/text.rb +1 -0
  40. data/lib/mechanize/form/textarea.rb +1 -0
  41. data/lib/mechanize/headers.rb +1 -0
  42. data/lib/mechanize/history.rb +2 -1
  43. data/lib/mechanize/http.rb +1 -0
  44. data/lib/mechanize/http/agent.rb +81 -38
  45. data/lib/mechanize/http/auth_challenge.rb +1 -0
  46. data/lib/mechanize/http/auth_realm.rb +2 -1
  47. data/lib/mechanize/http/auth_store.rb +1 -0
  48. data/lib/mechanize/http/content_disposition_parser.rb +18 -3
  49. data/lib/mechanize/http/www_authenticate_parser.rb +4 -4
  50. data/lib/mechanize/image.rb +1 -0
  51. data/lib/mechanize/page.rb +8 -5
  52. data/lib/mechanize/page/base.rb +1 -0
  53. data/lib/mechanize/page/frame.rb +4 -1
  54. data/lib/mechanize/page/image.rb +1 -0
  55. data/lib/mechanize/page/label.rb +1 -0
  56. data/lib/mechanize/page/link.rb +8 -1
  57. data/lib/mechanize/page/meta_refresh.rb +1 -0
  58. data/lib/mechanize/parser.rb +4 -3
  59. data/lib/mechanize/pluggable_parsers.rb +1 -0
  60. data/lib/mechanize/prependable.rb +1 -0
  61. data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
  62. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
  63. data/lib/mechanize/response_code_error.rb +2 -1
  64. data/lib/mechanize/response_read_error.rb +1 -0
  65. data/lib/mechanize/robots_disallowed_error.rb +1 -0
  66. data/lib/mechanize/test_case.rb +34 -29
  67. data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
  68. data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
  69. data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
  70. data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
  71. data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
  72. data/lib/mechanize/test_case/form_servlet.rb +1 -0
  73. data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
  74. data/lib/mechanize/test_case/header_servlet.rb +1 -0
  75. data/lib/mechanize/test_case/http_refresh_servlet.rb +2 -2
  76. data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
  77. data/lib/mechanize/test_case/infinite_refresh_servlet.rb +2 -2
  78. data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
  79. data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
  80. data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
  81. data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
  82. data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
  83. data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
  84. data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
  85. data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
  86. data/lib/mechanize/test_case/referer_servlet.rb +1 -0
  87. data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
  88. data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
  89. data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
  90. data/lib/mechanize/test_case/robots_txt_servlet.rb +15 -0
  91. data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
  92. data/lib/mechanize/test_case/server.rb +1 -0
  93. data/lib/mechanize/test_case/servlets.rb +4 -0
  94. data/lib/mechanize/test_case/verb_servlet.rb +5 -6
  95. data/lib/mechanize/unauthorized_error.rb +2 -1
  96. data/lib/mechanize/unsupported_scheme_error.rb +1 -0
  97. data/lib/mechanize/util.rb +5 -3
  98. data/lib/mechanize/version.rb +2 -1
  99. data/lib/mechanize/xml_file.rb +1 -0
  100. data/mechanize.gemspec +39 -31
  101. data/test/htdocs/dir with spaces/foo.html +1 -0
  102. data/test/htdocs/find_link.html +1 -4
  103. data/test/htdocs/tc_links.html +1 -1
  104. data/test/test_mechanize.rb +57 -15
  105. data/test/test_mechanize_cookie.rb +75 -60
  106. data/test/test_mechanize_cookie_jar.rb +112 -59
  107. data/test/test_mechanize_download.rb +13 -1
  108. data/test/test_mechanize_file.rb +10 -0
  109. data/test/test_mechanize_file_connection.rb +21 -3
  110. data/test/test_mechanize_file_response.rb +26 -2
  111. data/test/test_mechanize_form.rb +27 -11
  112. data/test/test_mechanize_form_check_box.rb +10 -0
  113. data/test/test_mechanize_form_encoding.rb +1 -1
  114. data/test/test_mechanize_form_keygen.rb +1 -0
  115. data/test/test_mechanize_form_multi_select_list.rb +5 -1
  116. data/test/test_mechanize_http_agent.rb +116 -8
  117. data/test/test_mechanize_http_auth_challenge.rb +14 -0
  118. data/test/test_mechanize_http_auth_realm.rb +7 -1
  119. data/test/test_mechanize_http_auth_store.rb +37 -0
  120. data/test/test_mechanize_http_content_disposition_parser.rb +35 -1
  121. data/test/test_mechanize_http_www_authenticate_parser.rb +16 -0
  122. data/test/test_mechanize_link.rb +47 -4
  123. data/test/test_mechanize_page.rb +29 -1
  124. data/test/test_mechanize_page_encoding.rb +23 -1
  125. data/test/test_mechanize_page_image.rb +1 -1
  126. data/test/test_mechanize_page_link.rb +3 -3
  127. data/test/test_mechanize_page_meta_refresh.rb +1 -1
  128. data/test/test_mechanize_parser.rb +12 -2
  129. data/test/test_mechanize_util.rb +1 -1
  130. metadata +105 -81
  131. data/.travis.yml +0 -25
  132. data/Manifest.txt +0 -204
  133. data/README.rdoc +0 -77
  134. data/test/htdocs/robots.txt +0 -2
@@ -46,6 +46,19 @@ class TestMechanizeDownload < Mechanize::TestCase
46
46
  end
47
47
  end
48
48
 
49
+ def test_save_bang_does_not_allow_command_injection
50
+ skip if windows?
51
+ uri = URI.parse 'http://example/foo.html'
52
+ body_io = StringIO.new '0123456789'
53
+
54
+ download = @parser.new uri, nil, body_io
55
+
56
+ in_tmpdir do
57
+ download.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
58
+ refute_operator(File, :exist?, "vul.txt")
59
+ end
60
+ end
61
+
49
62
  def test_save_tempfile
50
63
  uri = URI.parse 'http://example/foo.html'
51
64
  Tempfile.open @NAME do |body_io|
@@ -84,6 +97,5 @@ class TestMechanizeDownload < Mechanize::TestCase
84
97
 
85
98
  assert_equal "foo.html", download.filename
86
99
  end
87
-
88
100
  end
89
101
 
@@ -103,5 +103,15 @@ class TestMechanizeFile < Mechanize::TestCase
103
103
  end
104
104
  end
105
105
 
106
+ def test_save_bang_does_not_allow_command_injection
107
+ skip if windows?
108
+ uri = URI 'http://example/test.html'
109
+ page = Mechanize::File.new uri, nil, ''
110
+
111
+ in_tmpdir do
112
+ page.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
113
+ refute_operator(File, :exist?, "vul.txt")
114
+ end
115
+ end
106
116
  end
107
117
 
@@ -3,19 +3,37 @@ require 'mechanize/test_case'
3
3
  class TestMechanizeFileConnection < Mechanize::TestCase
4
4
 
5
5
  def test_request
6
- uri = URI.parse "file://#{File.expand_path __FILE__}"
6
+ file_path = File.expand_path(__FILE__)
7
+ uri = URI.parse "file://#{file_path}"
7
8
  conn = Mechanize::FileConnection.new
8
9
 
9
10
  body = ''
10
11
 
11
12
  conn.request uri, nil do |response|
13
+ assert_equal(file_path, response.file_path)
12
14
  response.read_body do |part|
13
15
  body << part
14
16
  end
15
17
  end
16
18
 
17
- assert_equal File.read(__FILE__), body
19
+ assert_equal File.read(__FILE__), body.gsub(/\r\n/, "\n")
18
20
  end
19
21
 
20
- end
22
+ def test_request_on_uri_with_windows_drive
23
+ uri_string = "file://C:/path/to/file.html"
24
+ expected_file_path = "C:/path/to/file.html"
25
+
26
+ uri = URI.parse(uri_string)
27
+ conn = Mechanize::FileConnection.new
21
28
 
29
+ called = false
30
+ yielded_file_path = nil
31
+ conn.request(uri, nil) do |response|
32
+ called = true
33
+ yielded_file_path = response.file_path
34
+ end
35
+
36
+ assert(called)
37
+ assert_equal(expected_file_path, yielded_file_path)
38
+ end
39
+ end
@@ -1,11 +1,15 @@
1
1
  require 'mechanize/test_case'
2
2
 
3
3
  class TestMechanizeFileResponse < Mechanize::TestCase
4
+ def test_file_path
5
+ res = Mechanize::FileResponse.new("/path/to/foo.html")
6
+ assert_equal("/path/to/foo.html", res.file_path)
7
+ end
4
8
 
5
9
  def test_content_type
6
10
  Tempfile.open %w[pi .nothtml] do |tempfile|
7
11
  res = Mechanize::FileResponse.new tempfile.path
8
- assert_equal nil, res['content-type']
12
+ assert_nil res['content-type']
9
13
  end
10
14
 
11
15
  Tempfile.open %w[pi .xhtml] do |tempfile|
@@ -19,5 +23,25 @@ class TestMechanizeFileResponse < Mechanize::TestCase
19
23
  end
20
24
  end
21
25
 
22
- end
26
+ def test_read_body
27
+ Tempfile.open %w[pi .html] do |tempfile|
28
+ tempfile.write("asdfasdfasdf")
29
+ tempfile.close
23
30
 
31
+ res = Mechanize::FileResponse.new(tempfile.path)
32
+ res.read_body do |input|
33
+ assert_equal("asdfasdfasdf", input)
34
+ end
35
+ end
36
+ end
37
+
38
+ def test_read_body_does_not_allow_command_injection
39
+ skip if windows?
40
+ in_tmpdir do
41
+ FileUtils.touch('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
42
+ res = Mechanize::FileResponse.new('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
43
+ res.read_body { |_| }
44
+ refute_operator(File, :exist?, "vul.txt")
45
+ end
46
+ end
47
+ end
@@ -65,6 +65,18 @@ class TestMechanizeForm < Mechanize::TestCase
65
65
  assert query.all? { |x| x[1] == '' }
66
66
  end
67
67
 
68
+ def test_build_query_blank_input_name
69
+ html = Nokogiri::HTML <<-HTML
70
+ <form>
71
+ <input type="text" name="" value="foo" />
72
+ </form>
73
+ HTML
74
+
75
+ form = Mechanize::Form.new html.at('form'), @mech, @page
76
+
77
+ assert_equal [], form.build_query
78
+ end
79
+
68
80
  def test_build_query_radio_button_duplicate
69
81
  html = Nokogiri::HTML <<-HTML
70
82
  <form>
@@ -214,7 +226,7 @@ class TestMechanizeForm < Mechanize::TestCase
214
226
 
215
227
  @form['name'] = 'Aaron'
216
228
 
217
- assert @form.has_field?('name')
229
+ assert_equal true, @form.has_field?('name')
218
230
  end
219
231
 
220
232
  def test_has_value_eh
@@ -222,7 +234,7 @@ class TestMechanizeForm < Mechanize::TestCase
222
234
 
223
235
  @form['name'] = 'Aaron'
224
236
 
225
- assert @form.has_value?('Aaron')
237
+ assert_equal true, @form.has_value?('Aaron')
226
238
  end
227
239
 
228
240
  def test_keys
@@ -863,15 +875,19 @@ class TestMechanizeForm < Mechanize::TestCase
863
875
  def test_form_and_fields_dom_id
864
876
  # blatant copypasta of test above
865
877
  page = @mech.get("http://localhost/form_test.html")
866
- form = page.form_with(:dom_id => 'generic_form')
867
- form_by_id = page.form_with(:id => 'generic_form')
878
+ form = page.form_with(dom_id: 'generic_form')
879
+
880
+ assert_equal(1, form.fields_with(dom_id: 'name_first').length)
881
+ assert_equal('first_name', form.field_with(dom_id: 'name_first').name)
868
882
 
869
- assert_equal(1, form.fields_with(:dom_id => 'name_first').length)
870
- assert_equal('first_name', form.field_with(:dom_id => 'name_first').name)
883
+ assert_equal(form, page.form_with(id: 'generic_form'))
884
+ assert_equal(form, page.form_with(css: '#generic_form'))
871
885
 
872
- # *_with(:id => blah) should work exactly like (:dom_id => blah)
873
- assert_equal(form, form_by_id)
874
- assert_equal(form.fields_with(:dom_id => 'name_first'), form.fields_with(:id => 'name_first'))
886
+ fields_by_dom_id = form.fields_with(dom_id: 'name_first')
887
+ assert_equal(fields_by_dom_id, form.fields_with(id: 'name_first'))
888
+ assert_equal(fields_by_dom_id, form.fields_with(css: '#name_first'))
889
+ assert_equal(fields_by_dom_id, form.fields_with(xpath: '//*[@id="name_first"]'))
890
+ assert_equal(fields_by_dom_id, form.fields_with(search: '//*[@id="name_first"]'))
875
891
  end
876
892
 
877
893
  def test_form_and_fields_dom_class
@@ -914,9 +930,9 @@ class TestMechanizeForm < Mechanize::TestCase
914
930
  page = @mech.get("http://localhost/form_multival.html")
915
931
  form = page.form_with(:name => 'post_form')
916
932
 
917
- assert(!form.has_field?('intarweb'))
933
+ assert_equal false, form.has_field?('intarweb')
918
934
  assert form.add_field!('intarweb')
919
- assert(form.has_field?('intarweb'))
935
+ assert_equal true, form.has_field?('intarweb')
920
936
  end
921
937
 
922
938
  def test_fill_unexisting_form
@@ -8,6 +8,16 @@ class TestMechanizeFormCheckBox < Mechanize::TestCase
8
8
  @page = @mech.get('http://localhost/tc_checkboxes.html')
9
9
  end
10
10
 
11
+ def test_search
12
+ form = @page.forms.first
13
+
14
+ checkbox = form.checkbox_with(name: 'green')
15
+ assert_equal('green', checkbox.name)
16
+
17
+ assert_equal(checkbox, form.checkbox_with('green'))
18
+ assert_equal(checkbox, form.checkbox_with(search: 'input[@type=checkbox][@name=green]'))
19
+ end
20
+
11
21
  def test_check
12
22
  form = @page.forms.first
13
23
 
@@ -67,7 +67,7 @@ class TestMechanizeFormEncoding < Mechanize::TestCase
67
67
  node['enctype'] = 'application/x-www-form-urlencoded'
68
68
  form = Mechanize::Form.new(node)
69
69
 
70
- assert_equal nil, form.encoding
70
+ assert_nil form.encoding
71
71
  end
72
72
 
73
73
  def test_post_form_with_form_encoding
@@ -22,6 +22,7 @@ class TestMechanizeFormKeygen < Mechanize::TestCase
22
22
  end
23
23
 
24
24
  def test_spki_signature
25
+ skip("JRuby PKI doesn't handle this for reasons I've been unable to understand") if RUBY_ENGINE=~/jruby/
25
26
  spki = OpenSSL::Netscape::SPKI.new @keygen.value
26
27
  assert_equal @keygen.challenge, spki.challenge
27
28
  assert_equal @keygen.key.public_key.to_pem, spki.public_key.to_pem
@@ -32,9 +32,13 @@ class TestMechanizeFormMultiSelectList < Mechanize::TestCase
32
32
  end
33
33
 
34
34
  def test_option_with
35
- option = @select.option_with :value => '1'
35
+ option = @select.option_with value: '1'
36
36
 
37
37
  assert_equal '1', option.value
38
+
39
+ option = @select.option_with search: 'option[@selected]'
40
+
41
+ assert_equal '2', option.value
38
42
  end
39
43
 
40
44
  def test_options_with
@@ -16,11 +16,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
16
16
  @res.instance_variable_set :@code, 200
17
17
  @res.instance_variable_set :@header, {}
18
18
 
19
- @headers = if RUBY_VERSION >= '2.0.0' then
20
- %w[accept accept-encoding user-agent]
21
- else
22
- %w[accept user-agent]
23
- end
19
+ @headers = %w[accept accept-encoding user-agent]
24
20
  end
25
21
 
26
22
  def auth_realm uri, scheme, type
@@ -205,7 +201,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
205
201
 
206
202
  page = @agent.fetch uri
207
203
 
208
- assert_equal File.read(foo), page.body
204
+ assert_equal File.read(foo), page.body.gsub(/\r\n/, "\n")
209
205
  assert_kind_of Mechanize::Page, page
210
206
  end
211
207
 
@@ -682,6 +678,14 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
682
678
  assert_equal 'absolute URL needed (not google)', e.message
683
679
  end
684
680
 
681
+ def test_resolve_uri_without_path
682
+ e = assert_raises ArgumentError do
683
+ @agent.resolve 'http:%5C%5Cfoo'
684
+ end
685
+
686
+ assert_equal 'hierarchical URL needed (not http:%5C%5Cfoo)', e.message
687
+ end
688
+
685
689
  def test_resolve_utf8
686
690
  uri = 'http://example?q=ü'
687
691
 
@@ -927,7 +931,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
927
931
  body_io = StringIO.new \
928
932
  "\037\213\b\0002\002\225M\000\003+H,*\001"
929
933
 
930
- return if jruby_zlib?
934
+ skip if jruby_zlib?
931
935
 
932
936
  e = assert_raises Mechanize::Error do
933
937
  @agent.response_content_encoding @res, body_io
@@ -1057,6 +1061,14 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1057
1061
  assert_equal 'part', body.read
1058
1062
  end
1059
1063
 
1064
+ def test_response_content_encoding_identity
1065
+ @res.instance_variable_set :@header, 'content-encoding' => %w[identity]
1066
+
1067
+ body = @agent.response_content_encoding @res, StringIO.new('part')
1068
+
1069
+ assert_equal 'part', body.read
1070
+ end
1071
+
1060
1072
  def test_response_content_encoding_tempfile_7_bit
1061
1073
  body_io = tempfile 'part'
1062
1074
 
@@ -1492,7 +1504,8 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1492
1504
  headers = {
1493
1505
  'Range' => 'bytes=0-9999',
1494
1506
  'Content-Type' => 'application/x-www-form-urlencoded',
1495
- 'Content-Length' => '9999',
1507
+ 'CONTENT-LENGTH' => '9999',
1508
+ 'content-md5' => '14758f1afd44c09b7992073ccf00b43d',
1496
1509
  }
1497
1510
 
1498
1511
  page = fake_page
@@ -1504,6 +1517,7 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1504
1517
  assert_match 'range|bytes=0-9999', page.body
1505
1518
  refute_match 'content-type|application/x-www-form-urlencoded', page.body
1506
1519
  refute_match 'content-length|9999', page.body
1520
+ refute_match 'content-md5|14758f1afd44c09b7992073ccf00b43d', page.body
1507
1521
  end
1508
1522
 
1509
1523
  def test_response_redirect_malformed
@@ -1539,6 +1553,48 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1539
1553
  end
1540
1554
  end
1541
1555
 
1556
+ def test_response_redirect_to_cross_site_with_credential
1557
+ @agent.redirect_ok = true
1558
+
1559
+ headers = {
1560
+ 'Range' => 'bytes=0-9999',
1561
+ 'AUTHORIZATION' => 'Basic xxx',
1562
+ 'cookie' => 'name=value',
1563
+ }
1564
+
1565
+ page = html_page ''
1566
+ page = @agent.response_redirect({ 'Location' => 'http://trap/http_headers' }, :get,
1567
+ page, 0, headers)
1568
+
1569
+ refute_includes(headers.keys, "AUTHORIZATION")
1570
+ refute_includes(headers.keys, "cookie")
1571
+
1572
+ assert_match 'range|bytes=0-9999', page.body
1573
+ refute_match("authorization|Basic xxx", page.body)
1574
+ refute_match("cookie|name=value", page.body)
1575
+ end
1576
+
1577
+ def test_response_redirect_to_same_site_with_credential
1578
+ @agent.redirect_ok = true
1579
+
1580
+ headers = {
1581
+ 'Range' => 'bytes=0-9999',
1582
+ 'AUTHORIZATION' => 'Basic xxx',
1583
+ 'cookie' => 'name=value',
1584
+ }
1585
+
1586
+ page = html_page ''
1587
+ page = @agent.response_redirect({ 'Location' => '/http_headers' }, :get,
1588
+ page, 0, headers)
1589
+
1590
+ assert_includes(headers.keys, "AUTHORIZATION")
1591
+ assert_includes(headers.keys, "cookie")
1592
+
1593
+ assert_match 'range|bytes=0-9999', page.body
1594
+ assert_match("authorization|Basic xxx", page.body)
1595
+ assert_match("cookie|name=value", page.body)
1596
+ end
1597
+
1542
1598
  def test_response_redirect_not_ok
1543
1599
  @agent.redirect_ok = false
1544
1600
 
@@ -1574,6 +1630,11 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1574
1630
  end
1575
1631
 
1576
1632
  def test_retry_change_request_equals
1633
+ unless Gem::Requirement.new("< 4.0.0").satisfied_by?(Gem::Version.new(Net::HTTP::Persistent::VERSION))
1634
+ # see https://github.com/drbrain/net-http-persistent/pull/100
1635
+ skip("net-http-persistent 4.0.0 and later does not support retry_change_requests")
1636
+ end
1637
+
1577
1638
  refute @agent.http.retry_change_requests
1578
1639
 
1579
1640
  @agent.retry_change_requests = true
@@ -1604,6 +1665,17 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1604
1665
  end
1605
1666
  end
1606
1667
 
1668
+ def test_robots_infinite_loop
1669
+ @agent.robots = true
1670
+ @agent.redirect_ok = true
1671
+
1672
+ assert_raises Mechanize::RobotsDisallowedError do
1673
+ @agent.fetch URI('http://301/norobots.html')
1674
+ end
1675
+
1676
+ @agent.fetch URI('http://301/robots.html')
1677
+ end
1678
+
1607
1679
  def test_set_proxy
1608
1680
  @agent.set_proxy 'www.example.com', 9001, 'joe', 'lol'
1609
1681
 
@@ -1639,6 +1711,42 @@ class TestMechanizeHttpAgent < Mechanize::TestCase
1639
1711
  assert_equal 'invalid value for port: "nonexistent service"', e.message
1640
1712
  end
1641
1713
 
1714
+ def test_set_proxy_with_scheme
1715
+ @agent.set_proxy 'http://www.example.com', 9001, 'joe', 'lol'
1716
+
1717
+ assert_equal @agent.proxy_uri.host, 'www.example.com'
1718
+ assert_equal @agent.proxy_uri.port, 9001
1719
+ assert_equal @agent.proxy_uri.user, 'joe'
1720
+ assert_equal @agent.proxy_uri.password, 'lol'
1721
+ end
1722
+
1723
+ def test_set_proxy_url
1724
+ @agent.set_proxy 'http://joe:lol@www.example.com:9001'
1725
+
1726
+ assert_equal @agent.proxy_uri.host, 'www.example.com'
1727
+ assert_equal @agent.proxy_uri.port, 9001
1728
+ assert_equal @agent.proxy_uri.user, 'joe'
1729
+ assert_equal @agent.proxy_uri.password, 'lol'
1730
+ end
1731
+
1732
+ def test_set_proxy_uri
1733
+ @agent.set_proxy URI('http://joe:lol@www.example.com:9001')
1734
+
1735
+ assert_equal @agent.proxy_uri.host, 'www.example.com'
1736
+ assert_equal @agent.proxy_uri.port, 9001
1737
+ assert_equal @agent.proxy_uri.user, 'joe'
1738
+ assert_equal @agent.proxy_uri.password, 'lol'
1739
+ end
1740
+
1741
+ def test_set_proxy_url_and_credentials
1742
+ @agent.set_proxy 'http://www.example.com:9001', nil, 'joe', 'lol'
1743
+
1744
+ assert_equal @agent.proxy_uri.host, 'www.example.com'
1745
+ assert_equal @agent.proxy_uri.port, 9001
1746
+ assert_equal @agent.proxy_uri.user, 'joe'
1747
+ assert_equal @agent.proxy_uri.password, 'lol'
1748
+ end
1749
+
1642
1750
  def test_setting_agent_name
1643
1751
  mech = Mechanize.new 'user-set-name'
1644
1752
  assert_equal 'user-set-name', mech.agent.http.name