mechanize 2.7.4 → 2.8.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.

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
@@ -25,6 +25,14 @@ class TestMechanizeHttpAuthChallenge < Mechanize::TestCase
25
25
  assert_equal expected, @challenge.realm(@uri + '/foo')
26
26
  end
27
27
 
28
+ def test_realm_digest_case
29
+ challenge = @AC.new 'Digest', { 'realm' => 'R' }, 'Digest realm=R'
30
+
31
+ expected = @AR.new 'Digest', @uri, 'R'
32
+
33
+ assert_equal expected, challenge.realm(@uri + '/foo')
34
+ end
35
+
28
36
  def test_realm_unknown
29
37
  @challenge.scheme = 'Unknown'
30
38
 
@@ -39,6 +47,12 @@ class TestMechanizeHttpAuthChallenge < Mechanize::TestCase
39
47
  assert_equal 'r', @challenge.realm_name
40
48
  end
41
49
 
50
+ def test_realm_name_case
51
+ challenge = @AC.new 'Digest', { 'realm' => 'R' }, 'Digest realm=R'
52
+
53
+ assert_equal 'R', challenge.realm_name
54
+ end
55
+
42
56
  def test_realm_name_ntlm
43
57
  challenge = @AC.new 'Negotiate, NTLM'
44
58
 
@@ -14,7 +14,10 @@ class TestMechanizeHttpAuthRealm < Mechanize::TestCase
14
14
  assert_equal 'r', @realm.realm
15
15
 
16
16
  realm = @AR.new 'Digest', @uri, 'R'
17
- assert_equal 'r', realm.realm
17
+ refute_equal 'r', realm.realm
18
+
19
+ realm = @AR.new 'Digest', @uri, 'R'
20
+ assert_equal 'R', realm.realm
18
21
 
19
22
  realm = @AR.new 'Digest', @uri, nil
20
23
  assert_nil realm.realm
@@ -30,6 +33,9 @@ class TestMechanizeHttpAuthRealm < Mechanize::TestCase
30
33
  other = @AR.new 'Digest', URI('http://other.example/'), 'r'
31
34
  refute_equal @realm, other
32
35
 
36
+ other = @AR.new 'Digest', @uri, 'R'
37
+ refute_equal @realm, other
38
+
33
39
  other = @AR.new 'Digest', @uri, 's'
34
40
  refute_equal @realm, other
35
41
  end
@@ -57,6 +57,20 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
57
57
  assert_equal expected, @store.auth_accounts
58
58
  end
59
59
 
60
+ def test_add_auth_realm_case
61
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
62
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
63
+
64
+ expected = {
65
+ @uri => {
66
+ 'realm' => ['user1', 'pass', nil],
67
+ 'Realm' => ['user2', 'pass', nil],
68
+ }
69
+ }
70
+
71
+ assert_equal expected, @store.auth_accounts
72
+ end
73
+
60
74
  def test_add_auth_string
61
75
  @store.add_auth "#{@uri}/path", 'user', 'pass'
62
76
 
@@ -143,6 +157,14 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
143
157
  assert_equal ['user1', 'pass', nil], @store.credentials_for(@uri, 'other')
144
158
  end
145
159
 
160
+ def test_credentials_for_realm_case
161
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
162
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
163
+
164
+ assert_equal ['user1', 'pass', nil], @store.credentials_for(@uri, 'realm')
165
+ assert_equal ['user2', 'pass', nil], @store.credentials_for(@uri, 'Realm')
166
+ end
167
+
146
168
  def test_credentials_for_path
147
169
  @store.add_auth @uri, 'user', 'pass', 'realm'
148
170
 
@@ -183,6 +205,21 @@ class TestMechanizeHttpAuthStore < Mechanize::TestCase
183
205
  assert_equal expected, @store.auth_accounts
184
206
  end
185
207
 
208
+ def test_remove_auth_realm_case
209
+ @store.add_auth @uri, 'user1', 'pass', 'realm'
210
+ @store.add_auth @uri, 'user2', 'pass', 'Realm'
211
+
212
+ @store.remove_auth @uri, 'Realm'
213
+
214
+ expected = {
215
+ @uri => {
216
+ 'realm' => ['user1', 'pass', nil]
217
+ }
218
+ }
219
+
220
+ assert_equal expected, @store.auth_accounts
221
+ end
222
+
186
223
  def test_remove_auth_string
187
224
  @store.add_auth @uri, 'user1', 'pass'
188
225
 
@@ -30,6 +30,33 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
30
30
  assert_equal expected, content_disposition.parameters
31
31
  end
32
32
 
33
+ def test_parse_date_iso8601_fallback
34
+ now = Time.at Time.now.to_i
35
+
36
+ content_disposition = @parser.parse \
37
+ 'attachment;' \
38
+ 'filename=value;' \
39
+ "creation-date=\"#{now.iso8601}\";" \
40
+ "modification-date=\"#{(now + 1).iso8601}\""
41
+
42
+ assert_equal 'attachment', content_disposition.type
43
+ assert_equal 'value', content_disposition.filename
44
+ assert_equal now, content_disposition.creation_date
45
+ assert_equal((now + 1), content_disposition.modification_date)
46
+ end
47
+
48
+ def test_parse_date_invalid
49
+ now = Time.at Time.now.to_i
50
+
51
+ content_disposition = @parser.parse \
52
+ 'attachment;' \
53
+ 'filename=value;' \
54
+ "creation-date=\"#{now.to_s}\";" \
55
+ "modification-date=\"#{(now + 1).to_s}\""
56
+
57
+ assert_nil content_disposition
58
+ end
59
+
33
60
  def test_parse_header
34
61
  content_disposition = @parser.parse \
35
62
  'content-disposition: attachment;filename=value', true
@@ -119,7 +146,7 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
119
146
 
120
147
  assert_equal 'end "', string
121
148
  end
122
-
149
+
123
150
  def test_parse_uppercase
124
151
  content_disposition = @parser.parse \
125
152
  'content-disposition: attachment; Filename=value', true
@@ -128,5 +155,12 @@ class TestMechanizeHttpContentDispositionParser < Mechanize::TestCase
128
155
  assert_equal 'value', content_disposition.filename
129
156
  end
130
157
 
158
+ def test_parse_filename_starting_with_escaped_quote
159
+ content_disposition = @parser.parse \
160
+ 'content-disposition: attachment; Filename="\"value\""', true
161
+
162
+ assert_equal '"value"', content_disposition.filename
163
+ end
164
+
131
165
  end
132
166
 
@@ -109,6 +109,14 @@ class TestMechanizeHttpWwwAuthenticateParser < Mechanize::TestCase
109
109
  assert_equal expected, @parser.parse('Basic ReAlM=foo')
110
110
  end
111
111
 
112
+ def test_parse_realm_value_case
113
+ expected = [
114
+ challenge('Basic', { 'realm' => 'Foo' }, 'Basic realm=Foo'),
115
+ ]
116
+
117
+ assert_equal expected, @parser.parse('Basic realm=Foo')
118
+ end
119
+
112
120
  def test_parse_scheme_uppercase
113
121
  expected = [
114
122
  challenge('Basic', { 'realm' => 'foo' }, 'BaSiC realm=foo'),
@@ -125,6 +133,14 @@ class TestMechanizeHttpWwwAuthenticateParser < Mechanize::TestCase
125
133
  assert_equal expected, @parser.parse('Basic realm = "foo"')
126
134
  end
127
135
 
136
+ def test_parse_bad_single_quote
137
+ expected = [
138
+ challenge('Basic', { 'realm' => "'foo" }, "Basic realm='foo"),
139
+ ]
140
+
141
+ assert_equal expected, @parser.parse("Basic realm='foo bar', qop='baz'")
142
+ end
143
+
128
144
  def test_quoted_string
129
145
  @parser.scanner = StringScanner.new '"text"'
130
146
 
@@ -2,6 +2,25 @@ require 'mechanize/test_case'
2
2
 
3
3
  class TestMechanizeLink < Mechanize::TestCase
4
4
 
5
+ def test_search
6
+ page = @mech.get("http://localhost/find_link.html")
7
+ link = page.link_with(text: "Form Test")
8
+
9
+ assert_equal('Form Test', link.text)
10
+
11
+ link_with_search = page.link_with(search: "//*[text()='Form Test']")
12
+ assert_equal(link, link_with_search)
13
+
14
+ link_with_xpath = page.link_with(xpath: "//*[text()='Form Test']")
15
+ assert_equal(link, link_with_xpath)
16
+
17
+ link_with_css = page.link_with(css: ".formtest")
18
+ assert_equal(link, link_with_css)
19
+
20
+ link_with_class = page.link_with(class: "formtest")
21
+ assert_equal(link, link_with_class)
22
+ end
23
+
5
24
  def test_click
6
25
  page = @mech.get("http://localhost/frame_test.html")
7
26
  link = page.link_with(:text => "Form Test")
@@ -10,7 +29,7 @@ class TestMechanizeLink < Mechanize::TestCase
10
29
  page = link.click
11
30
  assert_equal("http://localhost/form_test.html",
12
31
  @mech.history.last.uri.to_s)
13
- end
32
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
14
33
 
15
34
  def test_click_bang
16
35
  page = @mech.get("http://localhost/frame_test.html")
@@ -20,7 +39,7 @@ class TestMechanizeLink < Mechanize::TestCase
20
39
  page = link.click
21
40
  assert_equal("http://localhost/form_test.html",
22
41
  @mech.history.last.uri.to_s)
23
- end
42
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
24
43
 
25
44
  def test_click_base
26
45
  page = @mech.get("http://google.com/tc_base_link.html")
@@ -103,7 +122,7 @@ class TestMechanizeLink < Mechanize::TestCase
103
122
  page = page.link_with(:text => 'just the query string').click
104
123
  assert_equal('http://localhost/relative/tc_relative_links.html?a=b',
105
124
  page.uri.to_s)
106
- end
125
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse IFRAME
107
126
 
108
127
  def test_uri_weird
109
128
  doc = Nokogiri::HTML::Document.new
@@ -116,12 +135,36 @@ class TestMechanizeLink < Mechanize::TestCase
116
135
  assert_equal 'http://foo.bar/%20baz', link.uri.to_s
117
136
  end
118
137
 
138
+ def test_uri_weird_with_fragment
139
+ doc = Nokogiri::HTML::Document.new
140
+
141
+ node = Nokogiri::XML::Node.new('foo', doc)
142
+ node['href'] = 'http://foo.bar/ baz#уважение'
143
+
144
+ link = Mechanize::Page::Link.new(node, nil, nil)
145
+
146
+ assert_equal '%D1%83%D0%B2%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5', link.uri.fragment
147
+ end
148
+
149
+ def test_bad_uri_raise_compatible_exception
150
+ doc = Nokogiri::HTML::Document.new
151
+
152
+ node = Nokogiri::XML::Node.new('foo', doc)
153
+ node['href'] = 'http://http:foo.bar/ baz'
154
+
155
+ link = Mechanize::Page::Link.new(node, nil, nil)
156
+
157
+ assert_raises URI::InvalidURIError do
158
+ link.uri
159
+ end
160
+ end
161
+
119
162
  def test_resolving_full_uri
120
163
  page = @mech.get("http://localhost/frame_test.html")
121
164
  link = page.link_with(:text => "Form Test")
122
165
 
123
166
  assert_equal "/form_test.html", link.uri.to_s
124
167
  assert_equal "http://localhost/form_test.html", link.resolved_uri.to_s
125
- end
168
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
126
169
  end
127
170
 
@@ -108,6 +108,8 @@ class TestMechanizePage < Mechanize::TestCase
108
108
  assert_equal "frame3", page.frames[2].name
109
109
  assert_equal "/file_upload.html", page.frames[2].src
110
110
  assert_equal "File Upload Form", page.frames[2].content.title
111
+
112
+ assert_equal %w[/google.html /file_upload.html], page.frames_with(search: '*[name=frame1], *[name=frame3]').map(&:src)
111
113
  end
112
114
 
113
115
  def test_iframes
@@ -123,7 +125,7 @@ class TestMechanizePage < Mechanize::TestCase
123
125
  assert_equal "frame4", page.iframes.first.name
124
126
  assert_equal "/file_upload.html", page.iframes.first.src
125
127
  assert_equal "File Upload Form", page.iframes.first.content.title
126
- end
128
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse IFRAME
127
129
 
128
130
  def test_image_with
129
131
  page = html_page <<-BODY
@@ -248,5 +250,31 @@ class TestMechanizePage < Mechanize::TestCase
248
250
  assert_empty page.links_with(:search => '//img')
249
251
  end
250
252
 
253
+ def test_multiple_titles
254
+ page = html_page <<-BODY
255
+ <!doctype html>
256
+ <html>
257
+ <head>
258
+ <title>HTML&gt;TITLE</title>
259
+ </head>
260
+ <body>
261
+ <svg>
262
+ <title>SVGTITLE</title>
263
+ <metadata id="metadata5">
264
+ <rdf:RDF>
265
+ <cc:Work>
266
+ <dc:title>RDFDCTITLE</dc:title>
267
+ </cc:Work>
268
+ </rdf:RDF>
269
+ </metadata>
270
+ <g></g>
271
+ </svg>
272
+ </body>
273
+ </html>
274
+ BODY
275
+
276
+ assert_equal page.title, "HTML>TITLE"
277
+ end
278
+
251
279
  end
252
280
 
@@ -183,5 +183,27 @@ class TestMechanizePageEncoding < Mechanize::TestCase
183
183
  assert_equal Encoding::UTF_8, result.text.encoding
184
184
  end
185
185
 
186
- end
186
+ def test_parser_error_message_containing_encoding_errors
187
+ # https://github.com/sparklemotion/mechanize/issues/553
188
+ body = <<~EOF
189
+ <html>
190
+ <body>
191
+ <!--
192
+ ## メモ
193
+ 処理の一般化, 二重ループ, 多重ループ
194
+ wzxhzdk:25
195
+ -->
196
+ EOF
197
+ page = util_page body
187
198
 
199
+ # this should not raise an "invalid byte sequence in UTF-8" error while processing parsing errors
200
+ page.search("body")
201
+
202
+ # let's assert on the setup: a libxml2-returned parsing error itself contains an invalid character
203
+ assert(error = page.parser.errors.find { |e| e.message.include?("Comment not terminated") })
204
+ exception = assert_raises(ArgumentError) do
205
+ error.message =~ /any regex just to trigger encoding error/
206
+ end
207
+ assert_includes(exception.message, "invalid byte sequence in UTF-8")
208
+ end unless RUBY_ENGINE == 'jruby' # this is a libxml2-specific condition
209
+ end
@@ -147,7 +147,7 @@ class TestMechanizePageImage < Mechanize::TestCase
147
147
 
148
148
  assert_equal 'https', page.uri.scheme
149
149
  assert_equal false, page.images.first.relative?
150
- assert_equal nil, requests.first['Referer']
150
+ assert_nil requests.first['Referer']
151
151
  end
152
152
 
153
153
  def test_image_referer_http_page_abs_src
@@ -72,7 +72,7 @@ class TestMechanizePageLink < Mechanize::TestCase
72
72
  assert_equal(URI("http://localhost/canonical_uri"), page.canonical_uri)
73
73
 
74
74
  page = @mech.get("http://localhost/file_upload.html")
75
- assert_equal(nil, page.canonical_uri)
75
+ assert_nil page.canonical_uri
76
76
  end
77
77
 
78
78
  def test_canonical_uri_unescaped
@@ -290,7 +290,7 @@ class TestMechanizePageLink < Mechanize::TestCase
290
290
  def test_links
291
291
  page = @mech.get("http://localhost/find_link.html")
292
292
  assert_equal(18, page.links.length)
293
- end
293
+ end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse FRAME outside of FRAMESET
294
294
 
295
295
  def test_links_with_bold
296
296
  page = @mech.get("http://localhost/tc_links.html")
@@ -339,7 +339,7 @@ class TestMechanizePageLink < Mechanize::TestCase
339
339
  def test_title_none
340
340
  page = util_page '' # invalid HTML
341
341
 
342
- assert_equal(nil, page.title)
342
+ assert_nil(page.title)
343
343
  end
344
344
 
345
345
  def test_page_decoded_with_charset
@@ -112,7 +112,7 @@ class TestMechanizePageMetaRefresh < Mechanize::TestCase
112
112
  page = util_page 5, nil
113
113
  link = util_meta_refresh page
114
114
  assert_equal 5, link.delay
115
- assert_equal nil, link.href
115
+ assert_nil link.href
116
116
 
117
117
  page = util_page 5, @uri
118
118
  link = util_meta_refresh page
@@ -99,10 +99,10 @@ class TestMechanizeParser < Mechanize::TestCase
99
99
  @parser.uri = URI 'http://example'
100
100
 
101
101
  @parser.response = {
102
- 'content-disposition' => 'attachment; filename="some \"file\""'
102
+ 'content-disposition' => 'attachment; filename="\"some \"file\""'
103
103
  }
104
104
 
105
- assert_equal 'some__file_', @parser.extract_filename
105
+ assert_equal '_some__file_', @parser.extract_filename
106
106
  end
107
107
 
108
108
  def test_extract_filename_content_disposition_special
@@ -162,6 +162,16 @@ class TestMechanizeParser < Mechanize::TestCase
162
162
  end
163
163
  end
164
164
 
165
+ def test_extract_filename_content_disposition_empty
166
+ @parser.uri = URI 'http://example'
167
+
168
+ @parser.response = {
169
+ 'content-disposition' => 'inline; filename="/"'
170
+ }
171
+
172
+ assert_equal '', @parser.extract_filename
173
+ end
174
+
165
175
  def test_extract_filename_host
166
176
  @parser.response = {}
167
177
  @parser.uri = URI 'http://example'
@@ -27,7 +27,7 @@ class TestMechanizeUtil < Mechanize::TestCase
27
27
 
28
28
  def test_from_native_charset_returns_nil_when_no_string
29
29
  @result = @MU.from_native_charset(nil, CONTENT_ENCODING)
30
- assert_equal nil, @result
30
+ assert_nil @result
31
31
  end
32
32
 
33
33
  def test_from_native_charset_doesnot_convert_when_no_encoding