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.
- checksums.yaml +5 -5
- data/.github/workflows/ci-test.yml +45 -0
- data/.yardopts +8 -0
- data/{CHANGELOG.rdoc → CHANGELOG.md} +151 -86
- data/EXAMPLES.rdoc +1 -24
- data/Gemfile +1 -1
- data/{LICENSE.rdoc → LICENSE.txt} +4 -0
- data/README.md +77 -0
- data/Rakefile +18 -3
- data/examples/rubygems.rb +2 -2
- data/lib/mechanize.rb +3 -2
- data/lib/mechanize/chunked_termination_error.rb +1 -0
- data/lib/mechanize/content_type_error.rb +1 -0
- data/lib/mechanize/cookie.rb +1 -13
- data/lib/mechanize/cookie_jar.rb +4 -12
- data/lib/mechanize/directory_saver.rb +1 -0
- data/lib/mechanize/download.rb +2 -1
- data/lib/mechanize/element_matcher.rb +5 -1
- data/lib/mechanize/element_not_found_error.rb +1 -0
- data/lib/mechanize/file.rb +2 -1
- data/lib/mechanize/file_connection.rb +5 -3
- data/lib/mechanize/file_request.rb +1 -0
- data/lib/mechanize/file_response.rb +4 -1
- data/lib/mechanize/file_saver.rb +1 -0
- data/lib/mechanize/form.rb +112 -45
- data/lib/mechanize/form/button.rb +1 -0
- data/lib/mechanize/form/check_box.rb +1 -0
- data/lib/mechanize/form/field.rb +47 -0
- data/lib/mechanize/form/file_upload.rb +1 -0
- data/lib/mechanize/form/hidden.rb +1 -0
- data/lib/mechanize/form/image_button.rb +1 -0
- data/lib/mechanize/form/keygen.rb +1 -0
- data/lib/mechanize/form/multi_select_list.rb +8 -14
- data/lib/mechanize/form/option.rb +3 -1
- data/lib/mechanize/form/radio_button.rb +1 -0
- data/lib/mechanize/form/reset.rb +1 -0
- data/lib/mechanize/form/select_list.rb +1 -0
- data/lib/mechanize/form/submit.rb +1 -0
- data/lib/mechanize/form/text.rb +1 -0
- data/lib/mechanize/form/textarea.rb +1 -0
- data/lib/mechanize/headers.rb +1 -0
- data/lib/mechanize/history.rb +2 -1
- data/lib/mechanize/http.rb +1 -0
- data/lib/mechanize/http/agent.rb +81 -38
- data/lib/mechanize/http/auth_challenge.rb +1 -0
- data/lib/mechanize/http/auth_realm.rb +2 -1
- data/lib/mechanize/http/auth_store.rb +1 -0
- data/lib/mechanize/http/content_disposition_parser.rb +18 -3
- data/lib/mechanize/http/www_authenticate_parser.rb +4 -4
- data/lib/mechanize/image.rb +1 -0
- data/lib/mechanize/page.rb +8 -5
- data/lib/mechanize/page/base.rb +1 -0
- data/lib/mechanize/page/frame.rb +4 -1
- data/lib/mechanize/page/image.rb +1 -0
- data/lib/mechanize/page/label.rb +1 -0
- data/lib/mechanize/page/link.rb +8 -1
- data/lib/mechanize/page/meta_refresh.rb +1 -0
- data/lib/mechanize/parser.rb +4 -3
- data/lib/mechanize/pluggable_parsers.rb +1 -0
- data/lib/mechanize/prependable.rb +1 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
- data/lib/mechanize/response_code_error.rb +2 -1
- data/lib/mechanize/response_read_error.rb +1 -0
- data/lib/mechanize/robots_disallowed_error.rb +1 -0
- data/lib/mechanize/test_case.rb +34 -29
- data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
- data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
- data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
- data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
- data/lib/mechanize/test_case/form_servlet.rb +1 -0
- data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
- data/lib/mechanize/test_case/header_servlet.rb +1 -0
- data/lib/mechanize/test_case/http_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/infinite_refresh_servlet.rb +2 -2
- data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
- data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
- data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
- data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
- data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
- data/lib/mechanize/test_case/referer_servlet.rb +1 -0
- data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
- data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
- data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
- data/lib/mechanize/test_case/robots_txt_servlet.rb +15 -0
- data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
- data/lib/mechanize/test_case/server.rb +1 -0
- data/lib/mechanize/test_case/servlets.rb +4 -0
- data/lib/mechanize/test_case/verb_servlet.rb +5 -6
- data/lib/mechanize/unauthorized_error.rb +2 -1
- data/lib/mechanize/unsupported_scheme_error.rb +1 -0
- data/lib/mechanize/util.rb +5 -3
- data/lib/mechanize/version.rb +2 -1
- data/lib/mechanize/xml_file.rb +1 -0
- data/mechanize.gemspec +39 -31
- data/test/htdocs/dir with spaces/foo.html +1 -0
- data/test/htdocs/find_link.html +1 -4
- data/test/htdocs/tc_links.html +1 -1
- data/test/test_mechanize.rb +57 -15
- data/test/test_mechanize_cookie.rb +75 -60
- data/test/test_mechanize_cookie_jar.rb +112 -59
- data/test/test_mechanize_download.rb +13 -1
- data/test/test_mechanize_file.rb +10 -0
- data/test/test_mechanize_file_connection.rb +21 -3
- data/test/test_mechanize_file_response.rb +26 -2
- data/test/test_mechanize_form.rb +27 -11
- data/test/test_mechanize_form_check_box.rb +10 -0
- data/test/test_mechanize_form_encoding.rb +1 -1
- data/test/test_mechanize_form_keygen.rb +1 -0
- data/test/test_mechanize_form_multi_select_list.rb +5 -1
- data/test/test_mechanize_http_agent.rb +116 -8
- data/test/test_mechanize_http_auth_challenge.rb +14 -0
- data/test/test_mechanize_http_auth_realm.rb +7 -1
- data/test/test_mechanize_http_auth_store.rb +37 -0
- data/test/test_mechanize_http_content_disposition_parser.rb +35 -1
- data/test/test_mechanize_http_www_authenticate_parser.rb +16 -0
- data/test/test_mechanize_link.rb +47 -4
- data/test/test_mechanize_page.rb +29 -1
- data/test/test_mechanize_page_encoding.rb +23 -1
- data/test/test_mechanize_page_image.rb +1 -1
- data/test/test_mechanize_page_link.rb +3 -3
- data/test/test_mechanize_page_meta_refresh.rb +1 -1
- data/test/test_mechanize_parser.rb +12 -2
- data/test/test_mechanize_util.rb +1 -1
- metadata +105 -81
- data/.travis.yml +0 -25
- data/Manifest.txt +0 -204
- data/README.rdoc +0 -77
- 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
|
-
|
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
|
|
data/test/test_mechanize_link.rb
CHANGED
@@ -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
|
|
data/test/test_mechanize_page.rb
CHANGED
@@ -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>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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '
|
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'
|
data/test/test_mechanize_util.rb
CHANGED
@@ -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
|
-
|
30
|
+
assert_nil @result
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_from_native_charset_doesnot_convert_when_no_encoding
|