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.
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'stringio'
|
|
2
3
|
require 'zlib'
|
|
3
4
|
|
|
@@ -13,8 +14,8 @@ class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
if name = req.query['file'] then
|
|
16
|
-
open
|
|
17
|
-
string =
|
|
17
|
+
::File.open("#{TEST_DIR}/htdocs/#{name}") do |io|
|
|
18
|
+
string = String.new
|
|
18
19
|
zipped = StringIO.new string, 'w'
|
|
19
20
|
Zlib::GzipWriter.wrap zipped do |gz|
|
|
20
21
|
gz.write io.read
|
|
@@ -22,7 +23,7 @@ class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
|
22
23
|
res.body = string
|
|
23
24
|
end
|
|
24
25
|
else
|
|
25
|
-
res.body =
|
|
26
|
+
res.body = String.new
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
res['Content-Encoding'] = req['X-ResponseContentEncoding'] || 'gzip'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class HttpRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
2
3
|
def do_GET(req, res)
|
|
3
4
|
res['Content-Type'] = req.query['ct'] || "text/html"
|
|
4
5
|
refresh_time = req.query['refresh_time'] || 0
|
|
5
6
|
refresh_url = req.query['refresh_url'] || '/'
|
|
6
|
-
res['Refresh'] = " #{refresh_time};url=#{refresh_url}
|
|
7
|
+
res['Refresh'] = " #{refresh_time};url=#{refresh_url}";
|
|
7
8
|
end
|
|
8
9
|
end
|
|
9
|
-
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class InfiniteRefreshServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
2
3
|
def do_GET(req, res)
|
|
3
4
|
address = "#{req.host}:#{req.port}"
|
|
4
5
|
res['Content-Type'] = req.query['ct'] || "text/html"
|
|
5
6
|
res.status = req.query['code'] ? req.query['code'].to_i : '302'
|
|
6
7
|
number = req.query['q'] ? req.query['q'].to_i : 0
|
|
7
|
-
res['Refresh'] = "0;url=http://#{address}/infinite_refresh?q=#{number + 1}
|
|
8
|
+
res['Refresh'] = "0;url=http://#{address}/infinite_refresh?q=#{number + 1}";
|
|
8
9
|
end
|
|
9
10
|
end
|
|
10
|
-
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
class RobotsTxtServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
3
|
+
def do_GET(req, res)
|
|
4
|
+
if /301/ === req['Host'] && req.path == '/robots.txt'
|
|
5
|
+
res['Location'] = 'http://301/robots_txt'
|
|
6
|
+
res.code = 301
|
|
7
|
+
else
|
|
8
|
+
res['Content-Type'] = 'text/plain'
|
|
9
|
+
res.body = <<-'EOF'
|
|
10
|
+
User-Agent: *
|
|
11
|
+
Disallow: /norobots
|
|
12
|
+
EOF
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mechanize/test_case/bad_chunking_servlet'
|
|
2
3
|
require 'mechanize/test_case/basic_auth_servlet'
|
|
3
4
|
require 'mechanize/test_case/content_type_servlet'
|
|
@@ -21,6 +22,7 @@ require 'mechanize/test_case/referer_servlet'
|
|
|
21
22
|
require 'mechanize/test_case/refresh_with_empty_url'
|
|
22
23
|
require 'mechanize/test_case/refresh_without_url'
|
|
23
24
|
require 'mechanize/test_case/response_code_servlet'
|
|
25
|
+
require 'mechanize/test_case/robots_txt_servlet'
|
|
24
26
|
require 'mechanize/test_case/send_cookies_servlet'
|
|
25
27
|
require 'mechanize/test_case/verb_servlet'
|
|
26
28
|
|
|
@@ -49,6 +51,8 @@ MECHANIZE_TEST_CASE_SERVLETS = {
|
|
|
49
51
|
'/refresh_with_empty_url' => RefreshWithEmptyUrl,
|
|
50
52
|
'/refresh_without_url' => RefreshWithoutUrl,
|
|
51
53
|
'/response_code' => ResponseCodeServlet,
|
|
54
|
+
'/robots.txt' => RobotsTxtServlet,
|
|
55
|
+
'/robots_txt' => RobotsTxtServlet,
|
|
52
56
|
'/send_cookies' => SendCookiesServlet,
|
|
53
57
|
'/verb' => VerbServlet,
|
|
54
58
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class VerbServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
2
3
|
%w[HEAD GET POST PUT DELETE].each do |verb|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
8
|
-
METHOD
|
|
4
|
+
define_method "do_#{verb}" do |req, res|
|
|
5
|
+
res.header['X-Request-Method'] = verb
|
|
6
|
+
res.body = verb
|
|
7
|
+
end
|
|
9
8
|
end
|
|
10
9
|
end
|
|
11
10
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
class Mechanize::UnauthorizedError < Mechanize::ResponseCodeError
|
|
2
3
|
|
|
3
4
|
attr_reader :challenges
|
|
@@ -11,7 +12,7 @@ class Mechanize::UnauthorizedError < Mechanize::ResponseCodeError
|
|
|
11
12
|
out = super
|
|
12
13
|
|
|
13
14
|
if @challenges then
|
|
14
|
-
realms = @challenges.map
|
|
15
|
+
realms = @challenges.map(&:realm_name).join ', '
|
|
15
16
|
out << " -- available realms: #{realms}"
|
|
16
17
|
end
|
|
17
18
|
|
data/lib/mechanize/util.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'cgi'
|
|
2
3
|
require 'nkf'
|
|
3
4
|
|
|
@@ -15,7 +16,7 @@ class Mechanize::Util
|
|
|
15
16
|
def build_query_string(parameters, enc = nil)
|
|
16
17
|
each_parameter(parameters).inject(nil) { |s, (k, v)|
|
|
17
18
|
# WEBrick::HTTP.escape* has some problems about m17n on ruby-1.9.*.
|
|
18
|
-
(s.nil? ?
|
|
19
|
+
(s.nil? ? String.new : s << '&') << [CGI.escape(k.to_s), CGI.escape(v.to_s)].join('=')
|
|
19
20
|
} || ''
|
|
20
21
|
end
|
|
21
22
|
|
|
@@ -102,10 +103,11 @@ class Mechanize::Util
|
|
|
102
103
|
case NKF::BINARY
|
|
103
104
|
when Encoding
|
|
104
105
|
def self.guess_encoding(src)
|
|
105
|
-
NKF.guess
|
|
106
|
+
# NKF.guess of JRuby may return nil
|
|
107
|
+
NKF.guess(src) || Encoding::US_ASCII
|
|
106
108
|
end
|
|
107
109
|
else
|
|
108
|
-
# Old NKF from 1.8, still bundled with
|
|
110
|
+
# Old NKF from 1.8, still bundled with Rubinius
|
|
109
111
|
NKF_ENCODING_MAP = {
|
|
110
112
|
NKF::UNKNOWN => Encoding::US_ASCII,
|
|
111
113
|
NKF::BINARY => Encoding::ASCII_8BIT,
|
data/lib/mechanize/version.rb
CHANGED
data/lib/mechanize/xml_file.rb
CHANGED
data/mechanize.gemspec
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'mechanize/version'
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name
|
|
8
|
-
spec.version
|
|
9
|
-
spec.homepage
|
|
10
|
-
spec.summary
|
|
11
|
-
spec.description
|
|
8
|
+
spec.name = "mechanize"
|
|
9
|
+
spec.version = Mechanize::VERSION
|
|
10
|
+
spec.homepage = "https://github.com/sparklemotion/mechanize"
|
|
11
|
+
spec.summary = 'The Mechanize library is used for automating interaction with websites'
|
|
12
|
+
spec.description =
|
|
12
13
|
[
|
|
13
14
|
"The Mechanize library is used for automating interaction with websites.",
|
|
14
15
|
"Mechanize automatically stores and sends cookies, follows redirects,",
|
|
15
16
|
"and can follow links and submit forms. Form fields can be populated and",
|
|
16
17
|
"submitted. Mechanize also keeps track of the sites that you have visited as",
|
|
17
|
-
"a history."
|
|
18
|
+
"a history.",
|
|
18
19
|
].join("\n")
|
|
19
20
|
|
|
20
21
|
spec.authors =
|
|
@@ -23,39 +24,46 @@ Gem::Specification.new do |spec|
|
|
|
23
24
|
'Aaron Patterson',
|
|
24
25
|
'Mike Dalessio',
|
|
25
26
|
'Akinori MUSHA',
|
|
26
|
-
'Lee Jarvis'
|
|
27
|
+
'Lee Jarvis',
|
|
27
28
|
]
|
|
28
29
|
spec.email =
|
|
29
30
|
[
|
|
30
31
|
'drbrain@segment7.net',
|
|
31
|
-
'
|
|
32
|
+
'aaron.patterson@gmail.com',
|
|
32
33
|
'mike.dalessio@gmail.com',
|
|
33
34
|
'knu@idaemons.org',
|
|
34
|
-
'ljjarvis@gmail.com'
|
|
35
|
+
'ljjarvis@gmail.com',
|
|
35
36
|
]
|
|
36
37
|
|
|
37
|
-
spec.license
|
|
38
|
+
spec.license = "MIT"
|
|
38
39
|
|
|
39
40
|
spec.require_paths = ["lib"]
|
|
40
|
-
spec.files
|
|
41
|
-
spec.test_files
|
|
42
|
-
|
|
43
|
-
spec.extra_rdoc_files += Dir['*.rdoc']
|
|
44
|
-
spec.rdoc_options
|
|
45
|
-
|
|
46
|
-
spec.required_ruby_version = ">=
|
|
47
|
-
|
|
48
|
-
spec.add_runtime_dependency
|
|
49
|
-
spec.add_runtime_dependency
|
|
50
|
-
spec.add_runtime_dependency
|
|
51
|
-
spec.add_runtime_dependency
|
|
52
|
-
spec.add_runtime_dependency "
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
spec.
|
|
58
|
-
|
|
59
|
-
spec.
|
|
60
|
-
spec.
|
|
41
|
+
spec.files = %x(git ls-files).split($/)
|
|
42
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
|
43
|
+
|
|
44
|
+
spec.extra_rdoc_files += Dir['*.rdoc', '*.md']
|
|
45
|
+
spec.rdoc_options = ["--main", "README.md"]
|
|
46
|
+
|
|
47
|
+
spec.required_ruby_version = ">= 2.5.0"
|
|
48
|
+
|
|
49
|
+
spec.add_runtime_dependency("addressable", "~> 2.7")
|
|
50
|
+
spec.add_runtime_dependency("domain_name", ">= 0.5.20190701", "~> 0.5")
|
|
51
|
+
spec.add_runtime_dependency("http-cookie", ">= 1.0.3", "~> 1.0")
|
|
52
|
+
spec.add_runtime_dependency("mime-types", "~> 3.0")
|
|
53
|
+
spec.add_runtime_dependency("net-http-digest_auth", ">= 1.4.1", "~> 1.4")
|
|
54
|
+
|
|
55
|
+
# careful! some folks are relying on older versions of net-http-persistent
|
|
56
|
+
# - see the socks proxy patch in use at #507 and #464
|
|
57
|
+
# - see use of retry_change_requests that was removed at #558
|
|
58
|
+
spec.add_runtime_dependency("net-http-persistent", ">= 2.5.2", "< 5.0.dev")
|
|
59
|
+
|
|
60
|
+
spec.add_runtime_dependency("nokogiri", ">= 1.11.2", "~> 1.11")
|
|
61
|
+
spec.add_runtime_dependency("rubyntlm", ">= 0.6.3", "~> 0.6")
|
|
62
|
+
spec.add_runtime_dependency("webrick", "~> 1.7")
|
|
63
|
+
spec.add_runtime_dependency("webrobots", "~> 0.1.2")
|
|
64
|
+
|
|
65
|
+
spec.add_development_dependency("minitest", "~> 5.14")
|
|
66
|
+
spec.add_development_dependency("rake", "~> 13.0")
|
|
67
|
+
spec.add_development_dependency("rdoc", "~> 6.3")
|
|
68
|
+
spec.add_development_dependency("rubocop", "~> 1.12")
|
|
61
69
|
end
|
data/test/htdocs/find_link.html
CHANGED
|
@@ -11,13 +11,10 @@
|
|
|
11
11
|
<A HREF="http://blargle.com/">blargle</A>
|
|
12
12
|
<A HREF="http://a.cpan.org/">CPAN A</A>
|
|
13
13
|
<A HREF="http://b.cpan.org/">CPAN B</A>
|
|
14
|
-
<FRAME SRC="foo.html">
|
|
15
|
-
<FRAME SRC="bar.html">
|
|
16
14
|
<A HREF="http://c.cpan.org/" NAME="bongo">CPAN C</A>
|
|
17
15
|
<A HREF="http://d.cpan.org/">CPAN D</A>
|
|
18
16
|
|
|
19
17
|
<A HREF="http://www.msnbc.com/">MSNBC</A>
|
|
20
|
-
<FRAME SRC="http://www.oreilly.com/" NAME="wongo">
|
|
21
18
|
<A HREF="http://www.cnn.com/">CNN</A>
|
|
22
19
|
<A HREF="http://www.bbc.co.uk/" NAME="Wilma">BBC</A>
|
|
23
20
|
<A HREF="http://www.msnbc.com/">News</A>
|
|
@@ -35,7 +32,7 @@
|
|
|
35
32
|
<!-- new stuff -->
|
|
36
33
|
<A HREF="http://nowhere.org/" Name="Here">NoWhere</A>
|
|
37
34
|
<A HREF="http://nowhere.org/padded" Name=" Here "> NoWhere </A>
|
|
38
|
-
<A HREF="
|
|
35
|
+
<A HREF="form_test.html" class="formtest">Form Test</A>
|
|
39
36
|
</body>
|
|
40
37
|
</html>
|
|
41
38
|
|
data/test/htdocs/tc_links.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<a href="thing.html" class="thing_link">Thing!</a>
|
|
8
8
|
<a href="thing.html">Ruby <b>Rocks!</b></a>
|
|
9
9
|
<!-- Testing a bug with escaped stuff in links:
|
|
10
|
-
http://
|
|
10
|
+
http://rubygems.org/pipermail/mechanize-users/2006-September/000002.html
|
|
11
11
|
-->
|
|
12
12
|
<a href="link%20with%20space.html">encoded space</a>
|
|
13
13
|
<a href="link with space.html">not encoded space</a>
|
data/test/test_mechanize.rb
CHANGED
|
@@ -92,7 +92,7 @@ class TestMechanize < Mechanize::TestCase
|
|
|
92
92
|
|
|
93
93
|
assert_equal("http://localhost/form_test.html",
|
|
94
94
|
@mech.history.last.uri.to_s)
|
|
95
|
-
end
|
|
95
|
+
end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
|
|
96
96
|
|
|
97
97
|
def test_click_bogus_link_with_cookies
|
|
98
98
|
@mech.cookie_jar = cookie_jar("a=b")
|
|
@@ -149,7 +149,7 @@ class TestMechanize < Mechanize::TestCase
|
|
|
149
149
|
|
|
150
150
|
assert_equal("http://localhost/form_test.html",
|
|
151
151
|
@mech.history.last.uri.to_s)
|
|
152
|
-
end
|
|
152
|
+
end unless RUBY_ENGINE == 'jruby' # NekoHTML does not parse body of NOFRAMES
|
|
153
153
|
|
|
154
154
|
def test_click_link
|
|
155
155
|
link = node 'a', 'href' => '/index.html'
|
|
@@ -345,6 +345,15 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
345
345
|
end
|
|
346
346
|
end
|
|
347
347
|
|
|
348
|
+
def test_download_does_not_allow_command_injection
|
|
349
|
+
skip if windows?
|
|
350
|
+
in_tmpdir do
|
|
351
|
+
@mech.download('http://example', '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
|
|
352
|
+
|
|
353
|
+
refute_operator(File, :exist?, "vul.txt")
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
348
357
|
def test_get
|
|
349
358
|
uri = URI 'http://localhost'
|
|
350
359
|
|
|
@@ -374,6 +383,14 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
374
383
|
end
|
|
375
384
|
end
|
|
376
385
|
|
|
386
|
+
def test_get_auth
|
|
387
|
+
@mech.add_auth @uri, 'user', 'pass'
|
|
388
|
+
|
|
389
|
+
page = @mech.get @uri + '/basic_auth'
|
|
390
|
+
|
|
391
|
+
assert_equal 'You are authenticated', page.body
|
|
392
|
+
end
|
|
393
|
+
|
|
377
394
|
def test_get_auth_bad
|
|
378
395
|
@mech.add_auth(@uri, 'aaron', 'aaron')
|
|
379
396
|
|
|
@@ -392,6 +409,14 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
392
409
|
assert_equal("401", e.response_code)
|
|
393
410
|
end
|
|
394
411
|
|
|
412
|
+
def test_get_auth_realm
|
|
413
|
+
@mech.add_auth @uri, 'user', 'pass', 'Blah'
|
|
414
|
+
|
|
415
|
+
page = @mech.get @uri + '/basic_auth'
|
|
416
|
+
|
|
417
|
+
assert_equal 'You are authenticated', page.body
|
|
418
|
+
end
|
|
419
|
+
|
|
395
420
|
def test_get_conditional
|
|
396
421
|
assert_empty @mech.history
|
|
397
422
|
|
|
@@ -673,9 +698,7 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
673
698
|
end
|
|
674
699
|
|
|
675
700
|
def test_get_space
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
page = @mech.get("http://localhost/tc_bad_links.html ")
|
|
701
|
+
@mech.get("http://localhost/tc_bad_links.html ")
|
|
679
702
|
|
|
680
703
|
assert_match(/tc_bad_links.html$/, @mech.history.last.uri.to_s)
|
|
681
704
|
|
|
@@ -927,7 +950,26 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
927
950
|
"Content-Disposition: form-data; name=\"userfile1\"; filename=\"#{name}\"",
|
|
928
951
|
page.body
|
|
929
952
|
)
|
|
930
|
-
|
|
953
|
+
assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
def test_post_file_upload_nonascii
|
|
957
|
+
name = 'ユーザファイル1'
|
|
958
|
+
file_upload = Mechanize::Form::FileUpload.new({'name' => 'userfile1'}, name)
|
|
959
|
+
file_upload.file_data = File.read(__FILE__)
|
|
960
|
+
file_upload.mime_type = 'application/zip'
|
|
961
|
+
|
|
962
|
+
page = @mech.post('http://localhost/file_upload', {
|
|
963
|
+
:name => 'Some file',
|
|
964
|
+
:userfile1 => file_upload
|
|
965
|
+
})
|
|
966
|
+
|
|
967
|
+
assert_match(
|
|
968
|
+
"Content-Disposition: form-data; name=\"userfile1\"; filename=\"#{name}\"".force_encoding(Encoding::ASCII_8BIT),
|
|
969
|
+
page.body
|
|
970
|
+
)
|
|
971
|
+
assert_match("Content-Type: application/zip", page.body)
|
|
972
|
+
assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
|
|
931
973
|
end
|
|
932
974
|
|
|
933
975
|
def test_post_file_upload
|
|
@@ -946,7 +988,7 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
946
988
|
page.body
|
|
947
989
|
)
|
|
948
990
|
assert_match("Content-Type: application/zip", page.body)
|
|
949
|
-
|
|
991
|
+
assert_operator page.body.bytesize, :>, file_contents_without_cr(__FILE__).length
|
|
950
992
|
end
|
|
951
993
|
|
|
952
994
|
def test_post_redirect
|
|
@@ -1021,6 +1063,11 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
1021
1063
|
end
|
|
1022
1064
|
|
|
1023
1065
|
def test_retry_change_requests_equals
|
|
1066
|
+
unless Gem::Requirement.new("< 4.0.0").satisfied_by?(Gem::Version.new(Net::HTTP::Persistent::VERSION))
|
|
1067
|
+
# see https://github.com/drbrain/net-http-persistent/pull/100
|
|
1068
|
+
skip("net-http-persistent 4.0.0 and later does not support retry_change_requests")
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1024
1071
|
refute @mech.retry_change_requests
|
|
1025
1072
|
|
|
1026
1073
|
@mech.retry_change_requests = true
|
|
@@ -1052,25 +1099,21 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
1052
1099
|
|
|
1053
1100
|
assert_match(/Hello World/, @mech.current_page.body)
|
|
1054
1101
|
refute_empty @mech.cookies
|
|
1055
|
-
refute_empty Thread.current[@mech.agent.http.request_key]
|
|
1056
1102
|
|
|
1057
1103
|
@mech.shutdown
|
|
1058
1104
|
|
|
1059
|
-
assert_nil Thread.current[@mech.agent.http.request_key]
|
|
1060
1105
|
assert_empty @mech.history
|
|
1061
1106
|
assert_empty @mech.cookies
|
|
1062
1107
|
end
|
|
1063
1108
|
|
|
1064
1109
|
def test_start
|
|
1065
|
-
body
|
|
1110
|
+
body = nil
|
|
1066
1111
|
|
|
1067
1112
|
Mechanize.start do |m|
|
|
1068
1113
|
body = m.get("http://localhost/").body
|
|
1069
|
-
id = m.agent.http.request_key
|
|
1070
1114
|
end
|
|
1071
1115
|
|
|
1072
1116
|
assert_match(/Hello World/, body)
|
|
1073
|
-
assert_nil Thread.current[id]
|
|
1074
1117
|
end
|
|
1075
1118
|
|
|
1076
1119
|
def test_submit_bad_form_method
|
|
@@ -1140,7 +1183,7 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
1140
1183
|
|
|
1141
1184
|
page = @mech.submit(form)
|
|
1142
1185
|
|
|
1143
|
-
contents = File.
|
|
1186
|
+
contents = File.binread(__FILE__).gsub(/\r\n/, "\n")
|
|
1144
1187
|
basename = File.basename __FILE__
|
|
1145
1188
|
|
|
1146
1189
|
assert_match(
|
|
@@ -1160,7 +1203,7 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
1160
1203
|
|
|
1161
1204
|
page = @mech.submit(form)
|
|
1162
1205
|
|
|
1163
|
-
contents = File.
|
|
1206
|
+
contents = File.binread __FILE__
|
|
1164
1207
|
basename = File.basename __FILE__
|
|
1165
1208
|
assert_match(
|
|
1166
1209
|
"Content-Disposition: form-data; name=\"green[eggs]\"; filename=\"#{basename}\"",
|
|
@@ -1328,4 +1371,3 @@ but not <a href="/" rel="me nofollow">this</a>!
|
|
|
1328
1371
|
end
|
|
1329
1372
|
end
|
|
1330
1373
|
end
|
|
1331
|
-
|