kitamomonga-mechanize 0.9.3.20090724215219
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.
- data/CHANGELOG.rdoc +504 -0
- data/EXAMPLES.rdoc +171 -0
- data/FAQ.rdoc +11 -0
- data/GUIDE.rdoc +122 -0
- data/LICENSE.rdoc +340 -0
- data/Manifest.txt +176 -0
- data/README.rdoc +60 -0
- data/Rakefile +33 -0
- data/examples/flickr_upload.rb +23 -0
- data/examples/mech-dump.rb +7 -0
- data/examples/proxy_req.rb +9 -0
- data/examples/rubyforge.rb +21 -0
- data/examples/spider.rb +11 -0
- data/lib/mechanize.rb +666 -0
- data/lib/mechanize/chain.rb +34 -0
- data/lib/mechanize/chain/auth_headers.rb +78 -0
- data/lib/mechanize/chain/body_decoding_handler.rb +46 -0
- data/lib/mechanize/chain/connection_resolver.rb +76 -0
- data/lib/mechanize/chain/custom_headers.rb +21 -0
- data/lib/mechanize/chain/handler.rb +9 -0
- data/lib/mechanize/chain/header_resolver.rb +51 -0
- data/lib/mechanize/chain/parameter_resolver.rb +22 -0
- data/lib/mechanize/chain/post_connect_hook.rb +0 -0
- data/lib/mechanize/chain/post_page_hook.rb +18 -0
- data/lib/mechanize/chain/pre_connect_hook.rb +20 -0
- data/lib/mechanize/chain/request_resolver.rb +30 -0
- data/lib/mechanize/chain/response_body_parser.rb +38 -0
- data/lib/mechanize/chain/response_header_handler.rb +48 -0
- data/lib/mechanize/chain/response_reader.rb +39 -0
- data/lib/mechanize/chain/ssl_resolver.rb +40 -0
- data/lib/mechanize/chain/uri_resolver.rb +75 -0
- data/lib/mechanize/content_type_error.rb +14 -0
- data/lib/mechanize/cookie.rb +70 -0
- data/lib/mechanize/cookie_jar.rb +188 -0
- data/lib/mechanize/file.rb +71 -0
- data/lib/mechanize/file_response.rb +60 -0
- data/lib/mechanize/file_saver.rb +37 -0
- data/lib/mechanize/form.rb +364 -0
- data/lib/mechanize/form/button.rb +7 -0
- data/lib/mechanize/form/check_box.rb +11 -0
- data/lib/mechanize/form/field.rb +26 -0
- data/lib/mechanize/form/file_upload.rb +22 -0
- data/lib/mechanize/form/image_button.rb +21 -0
- data/lib/mechanize/form/multi_select_list.rb +67 -0
- data/lib/mechanize/form/option.rb +49 -0
- data/lib/mechanize/form/radio_button.rb +36 -0
- data/lib/mechanize/form/select_list.rb +43 -0
- data/lib/mechanize/headers.rb +11 -0
- data/lib/mechanize/history.rb +65 -0
- data/lib/mechanize/inspect.rb +88 -0
- data/lib/mechanize/monkey_patch.rb +35 -0
- data/lib/mechanize/page.rb +279 -0
- data/lib/mechanize/page/base.rb +8 -0
- data/lib/mechanize/page/encoding.rb +61 -0
- data/lib/mechanize/page/frame.rb +20 -0
- data/lib/mechanize/page/link.rb +53 -0
- data/lib/mechanize/page/meta.rb +50 -0
- data/lib/mechanize/pluggable_parsers.rb +101 -0
- data/lib/mechanize/redirect_limit_reached_error.rb +16 -0
- data/lib/mechanize/redirect_not_get_or_head_error.rb +18 -0
- data/lib/mechanize/response_code_error.rb +22 -0
- data/lib/mechanize/unsupported_scheme_error.rb +8 -0
- data/lib/mechanize/util.rb +73 -0
- data/test/chain/test_argument_validator.rb +14 -0
- data/test/chain/test_auth_headers.rb +25 -0
- data/test/chain/test_custom_headers.rb +18 -0
- data/test/chain/test_header_resolver.rb +28 -0
- data/test/chain/test_parameter_resolver.rb +35 -0
- data/test/chain/test_request_resolver.rb +29 -0
- data/test/chain/test_response_reader.rb +24 -0
- data/test/data/htpasswd +1 -0
- data/test/data/server.crt +16 -0
- data/test/data/server.csr +12 -0
- data/test/data/server.key +15 -0
- data/test/data/server.pem +15 -0
- data/test/helper.rb +129 -0
- data/test/htdocs/alt_text.html +10 -0
- data/test/htdocs/bad_form_test.html +9 -0
- data/test/htdocs/button.jpg +0 -0
- data/test/htdocs/empty_form.html +6 -0
- data/test/htdocs/file_upload.html +26 -0
- data/test/htdocs/find_link.html +41 -0
- data/test/htdocs/form_multi_select.html +16 -0
- data/test/htdocs/form_multival.html +37 -0
- data/test/htdocs/form_no_action.html +18 -0
- data/test/htdocs/form_no_input_name.html +16 -0
- data/test/htdocs/form_select.html +16 -0
- data/test/htdocs/form_select_all.html +16 -0
- data/test/htdocs/form_select_none.html +17 -0
- data/test/htdocs/form_select_noopts.html +10 -0
- data/test/htdocs/form_set_fields.html +14 -0
- data/test/htdocs/form_test.html +188 -0
- data/test/htdocs/frame_test.html +30 -0
- data/test/htdocs/google.html +13 -0
- data/test/htdocs/iframe_test.html +16 -0
- data/test/htdocs/index.html +6 -0
- data/test/htdocs/link with space.html +5 -0
- data/test/htdocs/meta_cookie.html +11 -0
- data/test/htdocs/no_title_test.html +6 -0
- data/test/htdocs/relative/tc_relative_links.html +21 -0
- data/test/htdocs/tc_bad_charset.html +9 -0
- data/test/htdocs/tc_bad_links.html +5 -0
- data/test/htdocs/tc_base_link.html +8 -0
- data/test/htdocs/tc_blank_form.html +11 -0
- data/test/htdocs/tc_charset.html +6 -0
- data/test/htdocs/tc_checkboxes.html +19 -0
- data/test/htdocs/tc_encoded_links.html +5 -0
- data/test/htdocs/tc_follow_meta.html +8 -0
- data/test/htdocs/tc_form_action.html +48 -0
- data/test/htdocs/tc_links.html +19 -0
- data/test/htdocs/tc_no_attributes.html +16 -0
- data/test/htdocs/tc_pretty_print.html +17 -0
- data/test/htdocs/tc_radiobuttons.html +17 -0
- data/test/htdocs/tc_referer.html +10 -0
- data/test/htdocs/tc_relative_links.html +19 -0
- data/test/htdocs/tc_textarea.html +23 -0
- data/test/htdocs/test_bad_encoding.html +52 -0
- data/test/htdocs/unusual______.html +5 -0
- data/test/servlets.rb +365 -0
- data/test/ssl_server.rb +48 -0
- data/test/test_authenticate.rb +71 -0
- data/test/test_bad_links.rb +25 -0
- data/test/test_blank_form.rb +16 -0
- data/test/test_checkboxes.rb +61 -0
- data/test/test_content_type.rb +13 -0
- data/test/test_cookie_class.rb +338 -0
- data/test/test_cookie_jar.rb +362 -0
- data/test/test_cookies.rb +123 -0
- data/test/test_encoded_links.rb +20 -0
- data/test/test_errors.rb +49 -0
- data/test/test_follow_meta.rb +108 -0
- data/test/test_form_action.rb +52 -0
- data/test/test_form_as_hash.rb +61 -0
- data/test/test_form_button.rb +38 -0
- data/test/test_form_no_inputname.rb +15 -0
- data/test/test_forms.rb +577 -0
- data/test/test_frames.rb +25 -0
- data/test/test_get_headers.rb +73 -0
- data/test/test_gzipping.rb +22 -0
- data/test/test_hash_api.rb +45 -0
- data/test/test_history.rb +142 -0
- data/test/test_history_added.rb +16 -0
- data/test/test_html_unscape_forms.rb +39 -0
- data/test/test_if_modified_since.rb +20 -0
- data/test/test_keep_alive.rb +31 -0
- data/test/test_links.rb +127 -0
- data/test/test_mech.rb +289 -0
- data/test/test_mechanize_file.rb +72 -0
- data/test/test_meta.rb +65 -0
- data/test/test_multi_select.rb +106 -0
- data/test/test_no_attributes.rb +13 -0
- data/test/test_option.rb +18 -0
- data/test/test_page.rb +127 -0
- data/test/test_page_encoding.rb +298 -0
- data/test/test_pluggable_parser.rb +145 -0
- data/test/test_post_form.rb +34 -0
- data/test/test_pretty_print.rb +22 -0
- data/test/test_radiobutton.rb +75 -0
- data/test/test_redirect_limit_reached.rb +39 -0
- data/test/test_redirect_verb_handling.rb +43 -0
- data/test/test_referer.rb +39 -0
- data/test/test_relative_links.rb +40 -0
- data/test/test_request.rb +13 -0
- data/test/test_response_code.rb +52 -0
- data/test/test_save_file.rb +103 -0
- data/test/test_scheme.rb +63 -0
- data/test/test_select.rb +106 -0
- data/test/test_select_all.rb +15 -0
- data/test/test_select_none.rb +15 -0
- data/test/test_select_noopts.rb +16 -0
- data/test/test_set_fields.rb +44 -0
- data/test/test_ssl_server.rb +20 -0
- data/test/test_subclass.rb +14 -0
- data/test/test_textarea.rb +45 -0
- data/test/test_upload.rb +109 -0
- data/test/test_verbs.rb +25 -0
- metadata +320 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
class Mechanize
|
|
2
|
+
class Page < Mechanize::File
|
|
3
|
+
# This class encapsulates a Meta tag. Mechanize treats meta tags just
|
|
4
|
+
# like 'a' tags. Meta objects will contain links, but most likely will
|
|
5
|
+
# have no text.
|
|
6
|
+
class Meta < Link
|
|
7
|
+
|
|
8
|
+
# Matches the content attribute of a meta tag. After the match:
|
|
9
|
+
#
|
|
10
|
+
# $1:: delay
|
|
11
|
+
# $3:: url
|
|
12
|
+
#
|
|
13
|
+
CONTENT_REGEXP = /^\s*(\d+\.?\d*)(;|;\s*url=\s*['"]?(\S*?)['"]?)?\s*$/i
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
# Parses the delay and url from the content attribute of a meta tag.
|
|
17
|
+
# Parse requires the uri of the current page to infer a url when no
|
|
18
|
+
# url is specified. If a block is given, the parsed delay and url
|
|
19
|
+
# will be passed to it for further processing.
|
|
20
|
+
#
|
|
21
|
+
# Returns nil if the delay and url cannot be parsed.
|
|
22
|
+
#
|
|
23
|
+
# # <meta http-equiv="refresh" content="5;url=http://example.com/" />
|
|
24
|
+
# uri = URI.parse('http://current.com/')
|
|
25
|
+
#
|
|
26
|
+
# Meta.parse("5;url=http://example.com/", uri) # => ['5', 'http://example.com/']
|
|
27
|
+
# Meta.parse("5;url=", uri) # => ['5', 'http://current.com/']
|
|
28
|
+
# Meta.parse("5", uri) # => ['5', 'http://current.com/']
|
|
29
|
+
# Meta.parse("invalid content", uri) # => nil
|
|
30
|
+
#
|
|
31
|
+
def parse(content, uri)
|
|
32
|
+
if content && content =~ CONTENT_REGEXP
|
|
33
|
+
delay, url = $1, $3
|
|
34
|
+
|
|
35
|
+
url = case url
|
|
36
|
+
when nil, "" then uri.to_s
|
|
37
|
+
when /^http/i then url
|
|
38
|
+
else "http://#{uri.host}#{url}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
block_given? ? yield(delay, url) : [delay, url]
|
|
42
|
+
else
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'mechanize/file'
|
|
2
|
+
require 'mechanize/file_saver'
|
|
3
|
+
require 'mechanize/page'
|
|
4
|
+
|
|
5
|
+
class Mechanize
|
|
6
|
+
# = Synopsis
|
|
7
|
+
# This class is used to register and maintain pluggable parsers for
|
|
8
|
+
# Mechanize to use.
|
|
9
|
+
#
|
|
10
|
+
# A Pluggable Parser is a parser that Mechanize uses for any particular
|
|
11
|
+
# content type. Mechanize will ask PluggableParser for the class it
|
|
12
|
+
# should initialize given any content type. This class allows users to
|
|
13
|
+
# register their own pluggable parsers, or modify existing pluggable
|
|
14
|
+
# parsers.
|
|
15
|
+
#
|
|
16
|
+
# PluggableParser returns a Mechanize::File object for content types
|
|
17
|
+
# that it does not know how to handle. Mechanize::File provides
|
|
18
|
+
# basic functionality for any content type, so it is a good class to
|
|
19
|
+
# extend when building your own parsers.
|
|
20
|
+
# == Example
|
|
21
|
+
# To create your own parser, just create a class that takes four
|
|
22
|
+
# parameters in the constructor. Here is an example of registering
|
|
23
|
+
# a pluggable parser that handles CSV files:
|
|
24
|
+
# class CSVParser < Mechanize::File
|
|
25
|
+
# attr_reader :csv
|
|
26
|
+
# def initialize(uri=nil, response=nil, body=nil, code=nil)
|
|
27
|
+
# super(uri, response, body, code)
|
|
28
|
+
# @csv = CSV.parse(body)
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
# agent = Mechanize.new
|
|
32
|
+
# agent.pluggable_parser.csv = CSVParser
|
|
33
|
+
# agent.get('http://example.com/test.csv') # => CSVParser
|
|
34
|
+
# Now any page that returns the content type of 'text/csv' will initialize
|
|
35
|
+
# a CSVParser and return that object to the caller.
|
|
36
|
+
#
|
|
37
|
+
# To register a pluggable parser for a content type that pluggable parser
|
|
38
|
+
# does not know about, just use the hash syntax:
|
|
39
|
+
# agent.pluggable_parser['text/something'] = SomeClass
|
|
40
|
+
#
|
|
41
|
+
# To set the default parser, just use the 'defaut' method:
|
|
42
|
+
# agent.pluggable_parser.default = SomeClass
|
|
43
|
+
# Now all unknown content types will be instances of SomeClass.
|
|
44
|
+
class PluggableParser
|
|
45
|
+
CONTENT_TYPES = {
|
|
46
|
+
:html => 'text/html',
|
|
47
|
+
:wap => 'application/vnd.wap.xhtml+xml',
|
|
48
|
+
:xhtml => 'application/xhtml+xml',
|
|
49
|
+
:pdf => 'application/pdf',
|
|
50
|
+
:csv => 'text/csv',
|
|
51
|
+
:xml => 'text/xml',
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
attr_accessor :default
|
|
55
|
+
|
|
56
|
+
def initialize
|
|
57
|
+
@parsers = { CONTENT_TYPES[:html] => Page,
|
|
58
|
+
CONTENT_TYPES[:xhtml] => Page,
|
|
59
|
+
CONTENT_TYPES[:wap] => Page,
|
|
60
|
+
}
|
|
61
|
+
@default = File
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def parser(content_type)
|
|
65
|
+
content_type.nil? ? default : @parsers[content_type] || default
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def register_parser(content_type, klass)
|
|
69
|
+
@parsers[content_type] = klass
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def html=(klass)
|
|
73
|
+
register_parser(CONTENT_TYPES[:html], klass)
|
|
74
|
+
register_parser(CONTENT_TYPES[:xhtml], klass)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def xhtml=(klass)
|
|
78
|
+
register_parser(CONTENT_TYPES[:xhtml], klass)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def pdf=(klass)
|
|
82
|
+
register_parser(CONTENT_TYPES[:pdf], klass)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def csv=(klass)
|
|
86
|
+
register_parser(CONTENT_TYPES[:csv], klass)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def xml=(klass)
|
|
90
|
+
register_parser(CONTENT_TYPES[:xml], klass)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def [](content_type)
|
|
94
|
+
@parsers[content_type]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def []=(content_type, klass)
|
|
98
|
+
@parsers[content_type] = klass
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Mechanize
|
|
2
|
+
# Thrown when too many redirects are sent
|
|
3
|
+
class RedirectLimitReachedError < RuntimeError
|
|
4
|
+
attr_reader :page, :response_code, :redirects
|
|
5
|
+
def initialize(page, redirects)
|
|
6
|
+
@page = page
|
|
7
|
+
@redirects = redirects
|
|
8
|
+
@response_code = page.code
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"Maximum redirect limit (#{redirects}) reached"
|
|
13
|
+
end
|
|
14
|
+
alias :inspect :to_s
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Mechanize
|
|
2
|
+
# Thrown when a POST, PUT, or DELETE request results in a redirect
|
|
3
|
+
# see RFC 2616 10.3.2, 10.3.3 http://www.ietf.org/rfc/rfc2616.txt
|
|
4
|
+
class RedirectNotGetOrHeadError < RuntimeError
|
|
5
|
+
attr_reader :page, :response_code, :verb, :uri
|
|
6
|
+
def initialize(page, verb)
|
|
7
|
+
@page = page
|
|
8
|
+
@verb = verb
|
|
9
|
+
@uri = page.uri
|
|
10
|
+
@response_code = page.code
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_s
|
|
14
|
+
"#{@response_code} redirect received after a #{@verb} request"
|
|
15
|
+
end
|
|
16
|
+
alias :inspect :to_s
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class Mechanize
|
|
2
|
+
# =Synopsis
|
|
3
|
+
# This error is thrown when Mechanize encounters a response code it does
|
|
4
|
+
# not know how to handle. Currently, this exception will be thrown
|
|
5
|
+
# if Mechanize encounters response codes other than 200, 301, or 302.
|
|
6
|
+
# Any other response code is up to the user to handle.
|
|
7
|
+
class ResponseCodeError < RuntimeError
|
|
8
|
+
attr_reader :response_code
|
|
9
|
+
attr_reader :page
|
|
10
|
+
|
|
11
|
+
def initialize(page)
|
|
12
|
+
@page = page
|
|
13
|
+
@response_code = page.code
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
"#{response_code} => #{Net::HTTPResponse::CODE_TO_OBJ[response_code]}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def inspect; to_s; end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
|
|
3
|
+
class Mechanize
|
|
4
|
+
class Util
|
|
5
|
+
CODE_DIC = {
|
|
6
|
+
:JIS => "ISO-2022-JP",
|
|
7
|
+
:EUC => "EUC-JP",
|
|
8
|
+
:SJIS => "SHIFT_JIS",
|
|
9
|
+
:UTF8 => "UTF-8", :UTF16 => "UTF-16", :UTF32 => "UTF-32"}
|
|
10
|
+
|
|
11
|
+
NKF_TO_ICONV = {
|
|
12
|
+
'ASCII-8BIT' => 'CP1252',
|
|
13
|
+
'SHIFT_JIS' => 'CP932',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def build_query_string(parameters, enc=nil)
|
|
18
|
+
parameters.map { |k,v|
|
|
19
|
+
# WEBrick::HTTP.escape* has some problems about m17n on ruby-1.9.*.
|
|
20
|
+
[CGI.escape(k.to_s), CGI.escape(v.to_s)].join("=") if k
|
|
21
|
+
}.compact.join('&')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_native_charset(s, code=nil)
|
|
25
|
+
if Mechanize.html_parser == Nokogiri::HTML
|
|
26
|
+
return unless s
|
|
27
|
+
code ||= detect_charset(s)
|
|
28
|
+
Iconv.iconv("UTF-8", code, s).join("")
|
|
29
|
+
else
|
|
30
|
+
s
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def from_native_charset(s, code)
|
|
35
|
+
if Mechanize.html_parser == Nokogiri::HTML
|
|
36
|
+
return unless s
|
|
37
|
+
Iconv.iconv(code, "UTF-8", s).join("")
|
|
38
|
+
else
|
|
39
|
+
return s
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def html_unescape(s)
|
|
44
|
+
return s unless s
|
|
45
|
+
s.gsub(/&(\w+|#[0-9]+);/) { |match|
|
|
46
|
+
number = case match
|
|
47
|
+
when /&(\w+);/
|
|
48
|
+
Mechanize.html_parser::NamedCharacters[$1]
|
|
49
|
+
when /&#([0-9]+);/
|
|
50
|
+
$1.to_i
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
number ? ([number].pack('U') rescue match) : match
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def detect_charset(src)
|
|
58
|
+
tmp = NKF.guess(src || "<html></html>")
|
|
59
|
+
if RUBY_VERSION >= "1.9.0"
|
|
60
|
+
enc = tmp.to_s.upcase
|
|
61
|
+
else
|
|
62
|
+
enc = NKF.constants.find{|c|
|
|
63
|
+
NKF.const_get(c) == tmp
|
|
64
|
+
}
|
|
65
|
+
enc = CODE_DIC[enc.intern]
|
|
66
|
+
end
|
|
67
|
+
enc = NKF_TO_ICONV[enc] if NKF_TO_ICONV[enc]
|
|
68
|
+
enc || "CP1252"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestURIResolver < Test::Unit::TestCase
|
|
4
|
+
def test_handle
|
|
5
|
+
v = Mechanize::Chain.new([
|
|
6
|
+
Mechanize::Chain::URIResolver.new(Hash.new { |h,k|
|
|
7
|
+
h[k] = lambda { |u,r| u }
|
|
8
|
+
})
|
|
9
|
+
])
|
|
10
|
+
assert_raises(ArgumentError) { v.handle({}) }
|
|
11
|
+
assert_nothing_raised { v.handle({:uri => 'http://google.com/'}) }
|
|
12
|
+
assert_raises(RuntimeError) { v.handle({:uri => 'google'}) }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestAuthHeaders < Test::Unit::TestCase
|
|
4
|
+
def test_auth
|
|
5
|
+
url = URI.parse('http://www.anthonychaves.net/tests.xml')
|
|
6
|
+
digest = %Q!Digest realm="www.anthonychaves.net", qop="auth", algorithm=MD5, nonce="MTI0NTEyMTYyNjo0ZTY2MjhlZWMyZmM1ZjA0M2Y1Njc1MGU0YTA2MWY5OQ==", opaque="9f455d4e71e8d46a6d3aaef8bf8b0d9e"!
|
|
7
|
+
v = Mechanize::Chain.new([
|
|
8
|
+
Mechanize::Chain::AuthHeaders.new({(url.host) => :digest}, "anthony", "password", digest)
|
|
9
|
+
])
|
|
10
|
+
|
|
11
|
+
hash = {
|
|
12
|
+
:request => Net::HTTP::Get.new(url.request_uri),
|
|
13
|
+
:uri => url
|
|
14
|
+
}
|
|
15
|
+
v.handle(hash)
|
|
16
|
+
actual_authorization = hash[:request]['Authorization']
|
|
17
|
+
# The chain gave our request an Authorization header with client-generated values and derivatives.
|
|
18
|
+
# They should be scrubbed before comparing to the expected result because they change
|
|
19
|
+
# on each invokation
|
|
20
|
+
actual_authorization.gsub!(/cnonce=\"\w+?\"/, "cnonce=\"scrubbed_cnonce\"").gsub!(/response=\"\w+?\"/, "response=\"scrubbed_response\"")
|
|
21
|
+
|
|
22
|
+
expected_authorization = %Q!Digest username="anthony", qop=auth, uri="/tests.xml", algorithm="MD5", opaque="9f455d4e71e8d46a6d3aaef8bf8b0d9e", nonce="MTI0NTEyMTYyNjo0ZTY2MjhlZWMyZmM1ZjA0M2Y1Njc1MGU0YTA2MWY5OQ==", realm="www.anthonychaves.net", nc=00000001, cnonce="scrubbed_cnonce", response="scrubbed_response"!
|
|
23
|
+
assert_equal(expected_authorization, actual_authorization)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestCustomHeaders < Test::Unit::TestCase
|
|
4
|
+
def test_handle
|
|
5
|
+
v = Mechanize::Chain.new([
|
|
6
|
+
Mechanize::Chain::CustomHeaders.new
|
|
7
|
+
])
|
|
8
|
+
url = URI.parse('http://tenderlovemaking.com/')
|
|
9
|
+
hash = {
|
|
10
|
+
:request => Net::HTTP::Get.new(url.request_uri),
|
|
11
|
+
:headers => { 'Content-Length' => 300 }
|
|
12
|
+
}
|
|
13
|
+
v.handle(hash)
|
|
14
|
+
headers = hash[:request].to_hash
|
|
15
|
+
assert(headers.key?('content-length'))
|
|
16
|
+
assert_equal([300], headers['content-length'])
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestHeaderResolver < Test::Unit::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@chain = Mechanize::Chain.new([
|
|
6
|
+
Mechanize::Chain::HeaderResolver.new(
|
|
7
|
+
true,
|
|
8
|
+
300,
|
|
9
|
+
Mechanize::CookieJar.new,
|
|
10
|
+
'foobar',
|
|
11
|
+
{
|
|
12
|
+
'hello' => 'world',
|
|
13
|
+
'Content-Type' => 'utf-8'
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_handle
|
|
20
|
+
hash = {
|
|
21
|
+
:request => {},
|
|
22
|
+
:uri => URI.parse('http://google.com/')
|
|
23
|
+
}
|
|
24
|
+
@chain.handle(hash)
|
|
25
|
+
assert_equal 'world', hash[:request]['hello']
|
|
26
|
+
assert_equal 'utf-8', hash[:request]['Content-Type']
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestParameterResolver < Test::Unit::TestCase
|
|
4
|
+
def test_handle_get
|
|
5
|
+
v = Mechanize::Chain.new([
|
|
6
|
+
Mechanize::Chain::ParameterResolver.new
|
|
7
|
+
])
|
|
8
|
+
hash = {
|
|
9
|
+
:uri => URI.parse('http://google.com/'),
|
|
10
|
+
:params => { :q => 'hello' },
|
|
11
|
+
:verb => :get
|
|
12
|
+
}
|
|
13
|
+
assert_nothing_raised {
|
|
14
|
+
v.handle(hash)
|
|
15
|
+
}
|
|
16
|
+
assert_equal('q=hello', hash[:uri].query)
|
|
17
|
+
assert_equal([], hash[:params])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_handle_post
|
|
21
|
+
v = Mechanize::Chain.new([
|
|
22
|
+
Mechanize::Chain::ParameterResolver.new
|
|
23
|
+
])
|
|
24
|
+
hash = {
|
|
25
|
+
:uri => URI.parse('http://google.com/'),
|
|
26
|
+
:params => { :q => 'hello' },
|
|
27
|
+
:verb => :post
|
|
28
|
+
}
|
|
29
|
+
assert_nothing_raised {
|
|
30
|
+
v.handle(hash)
|
|
31
|
+
}
|
|
32
|
+
assert_equal('', hash[:uri].query.to_s)
|
|
33
|
+
assert_equal({ :q => 'hello' }, hash[:params])
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
|
2
|
+
|
|
3
|
+
class TestRequestResolver < Test::Unit::TestCase
|
|
4
|
+
def test_handle_get
|
|
5
|
+
v = Mechanize::Chain.new([
|
|
6
|
+
Mechanize::Chain::RequestResolver.new
|
|
7
|
+
])
|
|
8
|
+
hash = {
|
|
9
|
+
:uri => URI.parse('http://google.com'),
|
|
10
|
+
:verb => :get
|
|
11
|
+
}
|
|
12
|
+
assert_nothing_raised { v.handle(hash) }
|
|
13
|
+
assert_kind_of(Net::HTTP::Get, hash[:request])
|
|
14
|
+
assert_equal('/', hash[:request].path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_handle_post
|
|
18
|
+
v = Mechanize::Chain.new([
|
|
19
|
+
Mechanize::Chain::RequestResolver.new
|
|
20
|
+
])
|
|
21
|
+
hash = {
|
|
22
|
+
:uri => URI.parse('http://google.com'),
|
|
23
|
+
:verb => :post
|
|
24
|
+
}
|
|
25
|
+
assert_nothing_raised { v.handle(hash) }
|
|
26
|
+
assert_kind_of(Net::HTTP::Post, hash[:request])
|
|
27
|
+
assert_equal('/', hash[:request].path)
|
|
28
|
+
end
|
|
29
|
+
end
|