mechanize 1.0.0 → 1.0.1.beta.20110107104205
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.
- data/CHANGELOG.rdoc +19 -0
- data/EXAMPLES.rdoc +13 -13
- data/Manifest.txt +0 -1
- data/Rakefile +4 -9
- data/lib/mechanize/chain/body_decoding_handler.rb +2 -0
- data/lib/mechanize/chain/connection_resolver.rb +6 -55
- data/lib/mechanize/chain/header_resolver.rb +3 -12
- data/lib/mechanize/chain/parameter_resolver.rb +2 -2
- data/lib/mechanize/chain/request_resolver.rb +1 -0
- data/lib/mechanize/chain/response_body_parser.rb +4 -6
- data/lib/mechanize/chain/response_header_handler.rb +1 -15
- data/lib/mechanize/chain/uri_resolver.rb +2 -2
- data/lib/mechanize/chain.rb +4 -1
- data/lib/mechanize/cookie.rb +1 -1
- data/lib/mechanize/file.rb +7 -0
- data/lib/mechanize/form/field.rb +6 -0
- data/lib/mechanize/form.rb +16 -4
- data/lib/mechanize/headers.rb +14 -0
- data/lib/mechanize/page/link.rb +7 -1
- data/lib/mechanize/page/meta.rb +3 -5
- data/lib/mechanize/page.rb +17 -4
- data/lib/mechanize/util.rb +8 -4
- data/lib/mechanize.rb +82 -56
- data/test/chain/test_header_resolver.rb +0 -2
- data/test/chain/test_parameter_resolver.rb +1 -1
- data/test/helper.rb +20 -13
- data/test/htdocs/form_multival.html +2 -2
- data/test/htdocs/form_test.html +2 -2
- data/test/htdocs/tc_links.html +1 -1
- data/test/htdocs/tc_referer.html +2 -0
- data/test/servlets.rb +41 -5
- data/test/test_authenticate.rb +3 -3
- data/test/test_cookies.rb +10 -4
- data/test/test_errors.rb +1 -1
- data/test/test_field_precedence.rb +4 -1
- data/test/test_follow_meta.rb +3 -3
- data/test/test_form_button.rb +8 -0
- data/test/test_forms.rb +63 -42
- data/test/test_gzipping.rb +1 -1
- data/test/test_headers.rb +33 -0
- data/test/test_history.rb +2 -2
- data/test/test_history_added.rb +1 -1
- data/test/test_links.rb +9 -0
- data/test/test_mech.rb +22 -7
- data/test/test_mech_proxy.rb +4 -4
- data/test/test_meta.rb +5 -3
- data/test/test_no_attributes.rb +1 -1
- data/test/test_referer.rb +21 -3
- data/test/test_relative_links.rb +4 -4
- data/test/test_response_code.rb +1 -1
- data/test/test_scheme.rb +7 -0
- metadata +61 -18
- data/test/test_keep_alive.rb +0 -31
data/lib/mechanize.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require '
|
2
|
-
require 'net/
|
1
|
+
require 'openssl'
|
2
|
+
require 'net/http/persistent'
|
3
3
|
require 'uri'
|
4
4
|
require 'webrick/httputils'
|
5
5
|
require 'zlib'
|
@@ -8,7 +8,9 @@ require 'digest/md5'
|
|
8
8
|
require 'fileutils'
|
9
9
|
require 'nokogiri'
|
10
10
|
require 'forwardable'
|
11
|
-
|
11
|
+
|
12
|
+
require 'iconv' if RUBY_VERSION < '1.9.2'
|
13
|
+
|
12
14
|
require 'nkf'
|
13
15
|
require 'mutex_m'
|
14
16
|
|
@@ -48,7 +50,7 @@ require 'mechanize/monkey_patch'
|
|
48
50
|
class Mechanize
|
49
51
|
##
|
50
52
|
# The version of Mechanize you are using.
|
51
|
-
VERSION = '1.0.
|
53
|
+
VERSION = '1.0.1.beta'
|
52
54
|
|
53
55
|
##
|
54
56
|
# User Agent aliases
|
@@ -74,7 +76,14 @@ class Mechanize
|
|
74
76
|
attr_accessor :key
|
75
77
|
attr_accessor :cert
|
76
78
|
attr_accessor :pass
|
79
|
+
|
80
|
+
# Controls how this agent deals with redirects. If it is set to
|
81
|
+
# true or :all, all 3xx redirects are automatically followed. This
|
82
|
+
# is the default behavior. If it is :permanent, only 301 (Moved
|
83
|
+
# Permanently) redirects are followed. If it is a false value, no
|
84
|
+
# redirects are followed.
|
77
85
|
attr_accessor :redirect_ok
|
86
|
+
|
78
87
|
attr_accessor :gzip_enabled
|
79
88
|
attr_accessor :keep_alive_time
|
80
89
|
attr_accessor :keep_alive
|
@@ -97,6 +106,8 @@ class Mechanize
|
|
97
106
|
# The HTML parser to be used when parsing documents
|
98
107
|
attr_accessor :html_parser
|
99
108
|
|
109
|
+
attr_reader :http # :nodoc:
|
110
|
+
|
100
111
|
attr_reader :history
|
101
112
|
attr_reader :pluggable_parser
|
102
113
|
|
@@ -131,7 +142,7 @@ class Mechanize
|
|
131
142
|
@cert = nil # OpenSSL Certificate
|
132
143
|
@key = nil # OpenSSL Private Key
|
133
144
|
@pass = nil # OpenSSL Password
|
134
|
-
@redirect_ok = true
|
145
|
+
@redirect_ok = true
|
135
146
|
@gzip_enabled = true
|
136
147
|
|
137
148
|
# attr_readers
|
@@ -145,19 +156,12 @@ class Mechanize
|
|
145
156
|
@auth_hash = {} # Keep track of urls for sending auth
|
146
157
|
@request_headers= {} # A hash of request headers to be used
|
147
158
|
|
148
|
-
# Proxy settings
|
149
|
-
@proxy_addr = nil
|
150
|
-
@proxy_pass = nil
|
151
|
-
@proxy_port = nil
|
152
|
-
@proxy_user = nil
|
153
|
-
|
154
159
|
@conditional_requests = true
|
155
160
|
|
156
161
|
@follow_meta_refresh = false
|
157
162
|
@redirection_limit = 20
|
158
163
|
|
159
164
|
# Connection Cache & Keep alive
|
160
|
-
@connection_cache = {}
|
161
165
|
@keep_alive_time = 300
|
162
166
|
@keep_alive = true
|
163
167
|
|
@@ -174,6 +178,7 @@ class Mechanize
|
|
174
178
|
@pre_connect_hook = Chain::PreConnectHook.new
|
175
179
|
@post_connect_hook = Chain::PostConnectHook.new
|
176
180
|
|
181
|
+
set_http
|
177
182
|
@html_parser = self.class.html_parser
|
178
183
|
|
179
184
|
yield self if block_given?
|
@@ -195,7 +200,14 @@ class Mechanize
|
|
195
200
|
# Sets the proxy address, port, user, and password
|
196
201
|
# +addr+ should be a host, with no "http://"
|
197
202
|
def set_proxy(addr, port, user = nil, pass = nil)
|
198
|
-
|
203
|
+
proxy = URI.parse "http://#{addr}"
|
204
|
+
proxy.port = port
|
205
|
+
proxy.user = user if user
|
206
|
+
proxy.password = pass if pass
|
207
|
+
|
208
|
+
set_http proxy
|
209
|
+
|
210
|
+
nil
|
199
211
|
end
|
200
212
|
|
201
213
|
# Set the user agent for the Mechanize object.
|
@@ -235,7 +247,7 @@ class Mechanize
|
|
235
247
|
end
|
236
248
|
|
237
249
|
unless referer
|
238
|
-
if url.to_s =~
|
250
|
+
if url.to_s =~ %r{\Ahttps?://}
|
239
251
|
referer = Page.new(nil, {'content-type'=>'text/html'})
|
240
252
|
else
|
241
253
|
referer = current_page || Page.new(nil, {'content-type'=>'text/html'})
|
@@ -306,13 +318,28 @@ class Mechanize
|
|
306
318
|
get(url).body
|
307
319
|
end
|
308
320
|
|
309
|
-
#
|
310
|
-
#
|
321
|
+
# If the parameter is a string, finds the button or link with the
|
322
|
+
# value of the string and clicks it. Otherwise, clicks the
|
323
|
+
# Mechanize::Page::Link object passed in. Returns the page fetched.
|
311
324
|
def click(link)
|
312
|
-
|
313
|
-
|
314
|
-
(
|
315
|
-
|
325
|
+
case link
|
326
|
+
when String, Regexp
|
327
|
+
if real_link = page.link_with(:text => link)
|
328
|
+
click real_link
|
329
|
+
else
|
330
|
+
button = nil
|
331
|
+
form = page.forms.find do |f|
|
332
|
+
button = f.button_with(:value => link)
|
333
|
+
button.is_a? Form::Submit
|
334
|
+
end
|
335
|
+
submit form, button if form
|
336
|
+
end
|
337
|
+
else
|
338
|
+
referer = link.page rescue referer = nil
|
339
|
+
href = link.respond_to?(:href) ? link.href :
|
340
|
+
(link['href'] || link['src'])
|
341
|
+
get(:url => href, :referer => (referer || current_page()))
|
342
|
+
end
|
316
343
|
end
|
317
344
|
|
318
345
|
# Equivalent to the browser back button. Returns the most recent page
|
@@ -439,12 +466,26 @@ class Mechanize
|
|
439
466
|
|
440
467
|
def resolve(url, referer = current_page())
|
441
468
|
hash = { :uri => url, :referer => referer }
|
442
|
-
|
469
|
+
Chain.new([
|
443
470
|
Chain::URIResolver.new(@scheme_handlers)
|
444
471
|
]).handle(hash)
|
445
472
|
hash[:uri].to_s
|
446
473
|
end
|
447
474
|
|
475
|
+
def set_http proxy = nil
|
476
|
+
@http = Net::HTTP::Persistent.new 'mechanize', proxy
|
477
|
+
|
478
|
+
@http.keep_alive = @keep_alive_time
|
479
|
+
|
480
|
+
@http.ca_file = @ca_file
|
481
|
+
@http.verify_callback = @verify_callback
|
482
|
+
|
483
|
+
if @cert and @key then
|
484
|
+
@http.certificate = OpenSSL::X509::Certificate.new ::File.read(@cert)
|
485
|
+
@http.private_key = OpenSSL::PKey::RSA.new ::File.read(@key), @pass
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
448
489
|
def post_form(url, form, headers = {})
|
449
490
|
cur_page = form.page || current_page ||
|
450
491
|
Page.new( nil, {'content-type'=>'text/html'})
|
@@ -485,19 +526,9 @@ class Mechanize
|
|
485
526
|
Chain::URIResolver.new(@scheme_handlers),
|
486
527
|
Chain::ParameterResolver.new,
|
487
528
|
Chain::RequestResolver.new,
|
488
|
-
Chain::ConnectionResolver.new
|
489
|
-
@connection_cache,
|
490
|
-
@keep_alive,
|
491
|
-
@proxy_addr,
|
492
|
-
@proxy_port,
|
493
|
-
@proxy_user,
|
494
|
-
@proxy_pass
|
495
|
-
),
|
496
|
-
Chain::SSLResolver.new(@ca_file, @verify_callback, @cert, @key, @pass),
|
529
|
+
Chain::ConnectionResolver.new,
|
497
530
|
Chain::AuthHeaders.new(@auth_hash, @user, @password, @digest),
|
498
531
|
Chain::HeaderResolver.new(
|
499
|
-
@keep_alive,
|
500
|
-
@keep_alive_time,
|
501
532
|
@cookie_jar,
|
502
533
|
@user_agent,
|
503
534
|
@gzip_enabled,
|
@@ -505,7 +536,8 @@ class Mechanize
|
|
505
536
|
),
|
506
537
|
Chain::CustomHeaders.new,
|
507
538
|
@pre_connect_hook,
|
508
|
-
])
|
539
|
+
], @http)
|
540
|
+
|
509
541
|
before_connect.handle(options)
|
510
542
|
|
511
543
|
uri = options[:uri]
|
@@ -520,11 +552,9 @@ class Mechanize
|
|
520
552
|
request['If-Modified-Since'] = page.response['Last-Modified']
|
521
553
|
end if(@conditional_requests)
|
522
554
|
|
523
|
-
http_obj.mu_lock
|
524
555
|
# Specify timeouts if given
|
525
556
|
http_obj.open_timeout = @open_timeout if @open_timeout
|
526
557
|
http_obj.read_timeout = @read_timeout if @read_timeout
|
527
|
-
http_obj.start unless http_obj.started?
|
528
558
|
|
529
559
|
# Log specified headers for the request
|
530
560
|
log.info("#{ request.class }: #{ request.path }") if log
|
@@ -533,32 +563,20 @@ class Mechanize
|
|
533
563
|
end if log
|
534
564
|
|
535
565
|
# Send the request
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
connection_chain.handle(options)
|
544
|
-
}
|
545
|
-
rescue EOFError, Errno::ECONNRESET, Errno::EPIPE => x
|
546
|
-
log.error("Rescuing EOF error") if log
|
547
|
-
http_obj.finish
|
548
|
-
raise x if attempts >= 2
|
549
|
-
request.body = nil
|
550
|
-
http_obj.start
|
551
|
-
attempts += 1
|
552
|
-
retry
|
553
|
-
end
|
566
|
+
response = http_obj.request(uri, request) { |r|
|
567
|
+
connection_chain = Chain.new([
|
568
|
+
Chain::ResponseReader.new(r),
|
569
|
+
Chain::BodyDecodingHandler.new,
|
570
|
+
])
|
571
|
+
connection_chain.handle(options)
|
572
|
+
}
|
554
573
|
|
555
574
|
after_connect = Chain.new([
|
556
575
|
@post_connect_hook,
|
557
576
|
Chain::ResponseBodyParser.new(@pluggable_parser, @watch_for_set),
|
558
|
-
Chain::ResponseHeaderHandler.new(@cookie_jar
|
577
|
+
Chain::ResponseHeaderHandler.new(@cookie_jar),
|
559
578
|
])
|
560
579
|
after_connect.handle(options)
|
561
|
-
http_obj.mu_unlock
|
562
580
|
|
563
581
|
res_klass = options[:res_klass]
|
564
582
|
response_body = options[:response_body]
|
@@ -581,6 +599,7 @@ class Mechanize
|
|
581
599
|
end
|
582
600
|
sleep delay.to_f
|
583
601
|
end
|
602
|
+
|
584
603
|
if redirect_uri
|
585
604
|
@history.push(page, page.uri)
|
586
605
|
return fetch_page(
|
@@ -599,7 +618,14 @@ class Mechanize
|
|
599
618
|
log.debug("Got cached page") if log
|
600
619
|
return visited_page(uri) || page
|
601
620
|
elsif res_klass <= Net::HTTPRedirection
|
602
|
-
|
621
|
+
case redirect_ok
|
622
|
+
when true, :all
|
623
|
+
# shortcut
|
624
|
+
when false, nil
|
625
|
+
return page
|
626
|
+
when :permanent
|
627
|
+
return page if res_klass != Net::HTTPMovedPermanently
|
628
|
+
end
|
603
629
|
log.info("follow redirect to: #{ response['Location'] }") if log
|
604
630
|
from_uri = page.uri
|
605
631
|
raise RedirectLimitReachedError.new(page, redirects) if redirects + 1 > redirection_limit
|
data/test/helper.rb
CHANGED
@@ -15,7 +15,7 @@ module MechTestHelper
|
|
15
15
|
</body></html>
|
16
16
|
END
|
17
17
|
html_response = { 'content-type' => 'text/html' }
|
18
|
-
|
18
|
+
Mechanize::Page.new( nil, html_response, html, 200, agent )
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -42,10 +42,12 @@ class Net::HTTP
|
|
42
42
|
'/many_cookies' => ManyCookiesTest,
|
43
43
|
'/many_cookies_as_string' => ManyCookiesAsStringTest,
|
44
44
|
'/send_cookies' => SendCookiesTest,
|
45
|
+
'/quoted_value_cookie' => QuotedValueCookieTest,
|
45
46
|
'/if_modified_since' => ModifiedSinceServlet,
|
46
47
|
'/http_headers' => HeaderServlet,
|
47
48
|
'/infinite_redirect' => InfiniteRedirectTest,
|
48
49
|
'/infinite_refresh' => InfiniteRefreshTest,
|
50
|
+
'/redirect_ok' => RedirectOkTest,
|
49
51
|
'/redirect' => RedirectTest,
|
50
52
|
'/refresh_without_url' => RefreshWithoutUrl,
|
51
53
|
'/refresh_with_empty_url' => RefreshWithEmptyUrl,
|
@@ -59,32 +61,36 @@ class Net::HTTP
|
|
59
61
|
|
60
62
|
def request(request, *data, &block)
|
61
63
|
url = URI.parse(request.path)
|
62
|
-
path =
|
64
|
+
path = WEBrick::HTTPUtils.unescape(url.path)
|
63
65
|
|
64
66
|
path = '/index.html' if path == '/'
|
65
67
|
|
66
68
|
res = Response.new
|
67
69
|
res.query_params = url.query
|
68
70
|
|
69
|
-
request.query =
|
71
|
+
request.query = if 'POST' != request.method && url.query then
|
72
|
+
WEBrick::HTTPUtils.parse_query url.query
|
73
|
+
elsif request['content-type'] =~ /www-form-urlencoded/ then
|
74
|
+
WEBrick::HTTPUtils.parse_query request.body
|
75
|
+
elsif request['content-type'] =~ /boundary=(.+)/ then
|
76
|
+
boundary = WEBrick::HTTPUtils.dequote $1
|
77
|
+
WEBrick::HTTPUtils.parse_form_data request.body, boundary
|
78
|
+
else
|
79
|
+
{}
|
80
|
+
end
|
81
|
+
|
70
82
|
request.cookies = WEBrick::Cookie.parse(request['Cookie'])
|
83
|
+
|
71
84
|
if SERVLETS[path]
|
72
|
-
if request.method == "POST"
|
73
|
-
if request['Content-Type'] =~ /^multipart\/form-data/
|
74
|
-
request.body = data.first
|
75
|
-
else
|
76
|
-
request.query = WEBrick::HTTPUtils.parse_query(data.first)
|
77
|
-
res.query_params = data.first
|
78
|
-
end
|
79
|
-
end
|
80
85
|
SERVLETS[path].new({}).send("do_#{request.method}", request, res)
|
81
86
|
else
|
82
|
-
filename = "htdocs#{path.gsub(/[^\/\\.\
|
87
|
+
filename = "htdocs#{path.gsub(/[^\/\\.\w\s]/, '_')}"
|
83
88
|
unless PAGE_CACHE[filename]
|
84
89
|
File.open("#{BASE_DIR}/#{filename}", 'rb') { |file|
|
85
90
|
PAGE_CACHE[filename] = file.read
|
86
91
|
}
|
87
92
|
end
|
93
|
+
|
88
94
|
res.body = PAGE_CACHE[filename]
|
89
95
|
end
|
90
96
|
|
@@ -109,7 +115,7 @@ class Response
|
|
109
115
|
|
110
116
|
attr_reader :code
|
111
117
|
attr_accessor :body, :query, :cookies
|
112
|
-
attr_accessor :query_params
|
118
|
+
attr_accessor :query_params, :http_version
|
113
119
|
|
114
120
|
def code=(c)
|
115
121
|
@code = c.to_s
|
@@ -124,6 +130,7 @@ class Response
|
|
124
130
|
@code = nil
|
125
131
|
@query = nil
|
126
132
|
@cookies = []
|
133
|
+
@http_version = '1.1'
|
127
134
|
end
|
128
135
|
|
129
136
|
def read_body
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<html>
|
2
2
|
<head><title>Page Title</title></head>
|
3
3
|
<body>
|
4
|
-
<form name="post_form" method="post" action="/form_post">
|
4
|
+
<form name="post_form" id="user_post_form" method="post" action="/form_post">
|
5
5
|
<table>
|
6
6
|
<tr>
|
7
7
|
<td>First Name</td>
|
8
|
-
<td><input name="first" type="text" /></td>
|
8
|
+
<td><input name="first" type="text" id="name_first" /></td>
|
9
9
|
</tr>
|
10
10
|
<tr>
|
11
11
|
<td>First Name Again</td>
|
data/test/htdocs/form_test.html
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
<head><title>Page Title</title></head>
|
3
3
|
<body>
|
4
4
|
<h1>Post Form 1</h1>
|
5
|
-
<form name="post_form1" method="post" action="/form_post">
|
5
|
+
<form name="post_form1" method="post" action="/form_post" id="generic_form" >
|
6
6
|
<table>
|
7
7
|
<tr>
|
8
8
|
<td>First Name</td>
|
9
|
-
<td><input type="text" name="first_name" /></td>
|
9
|
+
<td><input type="text" name="first_name" id="name_first" /></td>
|
10
10
|
</tr>
|
11
11
|
<tr>
|
12
12
|
<td>Gender</td>
|
data/test/htdocs/tc_links.html
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<a href="thing.html"><b>Bold Dude</b></a>
|
4
4
|
<a href="thing.html">Dude</a>
|
5
5
|
<a href="thing.html">Aaron <b>James</b> Patterson</a>
|
6
|
-
<a href="thing.html"><b>Aaron</b> Patterson</a>
|
6
|
+
<a href="thing.html" id="bold_aaron_link"><b>Aaron</b> Patterson</a>
|
7
7
|
<a href="thing.html">Ruby <b>Rocks!</b></a>
|
8
8
|
<!-- Testing a bug with escaped stuff in links:
|
9
9
|
http://rubyforge.org/pipermail/mechanize-users/2006-September/000002.html
|
data/test/htdocs/tc_referer.html
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
<html>
|
2
2
|
<body>
|
3
3
|
<a href="/referer">Referer Servlet</a>
|
4
|
+
<a href="http://localhost/referer">Referer Servlet forced to http</a>
|
5
|
+
<a href="https://localhost/referer">Referer Servlet forced to https</a>
|
4
6
|
<br />
|
5
7
|
<form method="post" action="/referer">
|
6
8
|
<input type="text" name="first" /></br>
|
data/test/servlets.rb
CHANGED
@@ -28,7 +28,7 @@ class BasicAuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
28
28
|
begin
|
29
29
|
authenticator.authenticate(req,res)
|
30
30
|
res.body = 'You are authenticated'
|
31
|
-
rescue WEBrick::HTTPStatus::Unauthorized
|
31
|
+
rescue WEBrick::HTTPStatus::Unauthorized
|
32
32
|
res.status = 401
|
33
33
|
end
|
34
34
|
FileUtils.rm('dot.htpasswd')
|
@@ -54,7 +54,7 @@ class DigestAuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
54
54
|
begin
|
55
55
|
@@authenticator.authenticate(req,res)
|
56
56
|
res.body = 'You are authenticated'
|
57
|
-
rescue WEBrick::HTTPStatus::Unauthorized
|
57
|
+
rescue WEBrick::HTTPStatus::Unauthorized
|
58
58
|
res.status = 401
|
59
59
|
end
|
60
60
|
FileUtils.rm('digest.htpasswd') if File.exists?('digest.htpasswd')
|
@@ -200,6 +200,29 @@ class InfiniteRedirectTest < WEBrick::HTTPServlet::AbstractServlet
|
|
200
200
|
alias :do_POST :do_GET
|
201
201
|
end
|
202
202
|
|
203
|
+
class RedirectOkTest < WEBrick::HTTPServlet::AbstractServlet
|
204
|
+
def do_GET(req, res)
|
205
|
+
res['Content-Type'] = "text/plain"
|
206
|
+
case q = req.query['q']
|
207
|
+
when '1'..'2'
|
208
|
+
res.status = '301'
|
209
|
+
q.succ!
|
210
|
+
when '3'..'4'
|
211
|
+
res.status = '302'
|
212
|
+
q.succ!
|
213
|
+
when '5'
|
214
|
+
res.status = '200'
|
215
|
+
res.body = 'Finally OK.'
|
216
|
+
return
|
217
|
+
else
|
218
|
+
res.status = '301'
|
219
|
+
q = '1'
|
220
|
+
end
|
221
|
+
res['Location'] = "/redirect_ok?q=#{q}"
|
222
|
+
end
|
223
|
+
alias :do_POST :do_GET
|
224
|
+
end
|
225
|
+
|
203
226
|
class RedirectTest < WEBrick::HTTPServlet::AbstractServlet
|
204
227
|
def do_GET(req, res)
|
205
228
|
res['Content-Type'] = req.query['ct'] || "text/html"
|
@@ -242,7 +265,7 @@ class FormTest < WEBrick::HTTPServlet::AbstractServlet
|
|
242
265
|
res.body = "<HTML><body>"
|
243
266
|
req.query.each_key { |k|
|
244
267
|
req.query[k].each_data { |data|
|
245
|
-
res.body << "<a href=\"#\">#{
|
268
|
+
res.body << "<a href=\"#\">#{WEBrick::HTTPUtils.unescape(k)}:#{WEBrick::HTTPUtils.unescape(data)}</a><br />"
|
246
269
|
}
|
247
270
|
}
|
248
271
|
res.body << "<div id=\"query\">#{res.query}</div></body></HTML>"
|
@@ -251,12 +274,14 @@ class FormTest < WEBrick::HTTPServlet::AbstractServlet
|
|
251
274
|
|
252
275
|
def do_POST(req, res)
|
253
276
|
res.body = "<HTML><body>"
|
277
|
+
|
254
278
|
req.query.each_key { |k|
|
255
279
|
req.query[k].each_data { |data|
|
256
280
|
res.body << "<a href=\"#\">#{k}:#{data}</a><br />"
|
257
281
|
}
|
258
282
|
}
|
259
|
-
|
283
|
+
|
284
|
+
res.body << "<div id=\"query\">#{req.body}</div></body></HTML>"
|
260
285
|
res['Content-Type'] = "text/html"
|
261
286
|
end
|
262
287
|
end
|
@@ -357,9 +382,20 @@ class SendCookiesTest < WEBrick::HTTPServlet::AbstractServlet
|
|
357
382
|
def do_GET(req, res)
|
358
383
|
res['Content-Type'] = "text/html"
|
359
384
|
res.body = "<html><body>"
|
360
|
-
req.cookies.each { |c|
|
385
|
+
req.cookies.each { |c|
|
361
386
|
res.body << "<a href=\"#\">#{c.name}:#{c.value}</a>"
|
362
387
|
}
|
363
388
|
res.body << "</body></html>"
|
364
389
|
end
|
365
390
|
end
|
391
|
+
|
392
|
+
class QuotedValueCookieTest < WEBrick::HTTPServlet::AbstractServlet
|
393
|
+
def do_GET(req, res)
|
394
|
+
cookie = WEBrick::Cookie.new("quoted", "\"value\"")
|
395
|
+
cookie.path = "/"
|
396
|
+
cookie.expires = Time.now + 86400
|
397
|
+
res.cookies << cookie
|
398
|
+
res['Content-Type'] = "text/html"
|
399
|
+
res.body = "<html><body>hello</body></html>"
|
400
|
+
end
|
401
|
+
end
|
data/test/test_authenticate.rb
CHANGED
@@ -27,7 +27,7 @@ class BasicAuthTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
}
|
29
29
|
@agent.basic_auth('user', 'pass')
|
30
|
-
|
30
|
+
@agent.get("http://localhost/digest_auth")
|
31
31
|
assert block_called
|
32
32
|
end
|
33
33
|
|
@@ -54,7 +54,7 @@ class BasicAuthTest < Test::Unit::TestCase
|
|
54
54
|
def test_auth_bad_user_pass
|
55
55
|
@agent.basic_auth('aaron', 'aaron')
|
56
56
|
begin
|
57
|
-
|
57
|
+
@agent.get("http://localhost/basic_auth")
|
58
58
|
rescue Mechanize::ResponseCodeError => e
|
59
59
|
assert_equal("401", e.response_code)
|
60
60
|
end
|
@@ -62,7 +62,7 @@ class BasicAuthTest < Test::Unit::TestCase
|
|
62
62
|
|
63
63
|
def test_auth_failure
|
64
64
|
begin
|
65
|
-
|
65
|
+
@agent.get("http://localhost/basic_auth")
|
66
66
|
rescue Mechanize::ResponseCodeError => e
|
67
67
|
assert_equal("401", e.response_code)
|
68
68
|
end
|
data/test/test_cookies.rb
CHANGED
@@ -5,9 +5,15 @@ class CookiesMechTest < Test::Unit::TestCase
|
|
5
5
|
@agent = Mechanize.new
|
6
6
|
end
|
7
7
|
|
8
|
+
def test_quoted_value_cookie
|
9
|
+
@agent.get("http://localhost/quoted_value_cookie")
|
10
|
+
quoted_cookie = @agent.cookies.find { |k| k.name == 'quoted' }
|
11
|
+
assert_equal("\"value\"", quoted_cookie.value)
|
12
|
+
end
|
13
|
+
|
8
14
|
def test_meta_tag_cookies
|
9
15
|
cookies = @agent.cookies.length
|
10
|
-
|
16
|
+
@agent.get("http://localhost/meta_cookie.html")
|
11
17
|
assert_equal(cookies + 1, @agent.cookies.length)
|
12
18
|
end
|
13
19
|
|
@@ -20,7 +26,7 @@ class CookiesMechTest < Test::Unit::TestCase
|
|
20
26
|
end
|
21
27
|
|
22
28
|
def test_no_space_cookies
|
23
|
-
|
29
|
+
@agent.get("http://localhost/one_cookie_no_space")
|
24
30
|
assert_equal(1, @agent.cookies.length)
|
25
31
|
foo_cookie = @agent.cookies.find { |k| k.name == 'foo' }
|
26
32
|
assert_not_nil(foo_cookie, 'Foo cookie was nil')
|
@@ -30,7 +36,7 @@ class CookiesMechTest < Test::Unit::TestCase
|
|
30
36
|
end
|
31
37
|
|
32
38
|
def test_many_cookies_as_string
|
33
|
-
|
39
|
+
@agent.get("http://localhost/many_cookies_as_string")
|
34
40
|
assert_equal(4, @agent.cookies.length)
|
35
41
|
|
36
42
|
name_cookie = @agent.cookies.find { |k| k.name == "name" }
|
@@ -61,7 +67,7 @@ class CookiesMechTest < Test::Unit::TestCase
|
|
61
67
|
end
|
62
68
|
|
63
69
|
def test_many_cookies
|
64
|
-
|
70
|
+
@agent.get("http://localhost/many_cookies")
|
65
71
|
assert_equal(4, @agent.cookies.length)
|
66
72
|
|
67
73
|
name_cookie = @agent.cookies.find { |k| k.name == "name" }
|
data/test/test_errors.rb
CHANGED
@@ -14,7 +14,7 @@ class MechErrorsTest < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
def test_non_exist
|
16
16
|
begin
|
17
|
-
|
17
|
+
@agent.get("http://localhost/bad_form_test.html")
|
18
18
|
rescue RuntimeError => ex
|
19
19
|
assert_equal("404", ex.inspect)
|
20
20
|
end
|
@@ -10,7 +10,10 @@ class TestFieldPrecedence < Test::Unit::TestCase
|
|
10
10
|
form = @page.forms.first
|
11
11
|
assert !form.checkboxes.empty?
|
12
12
|
assert_equal "1", form.checkboxes.first.value
|
13
|
-
|
13
|
+
|
14
|
+
submitted = form.submit
|
15
|
+
|
16
|
+
assert_equal 'ticky=1&ticky=0', submitted.parser.at('#query').text
|
14
17
|
end
|
15
18
|
|
16
19
|
def test_field_sort
|
data/test/test_follow_meta.rb
CHANGED
@@ -12,7 +12,7 @@ class FollowMetaTest < Test::Unit::TestCase
|
|
12
12
|
requests << params[:request]
|
13
13
|
}
|
14
14
|
|
15
|
-
|
15
|
+
@agent.get('http://localhost/tc_meta_in_body.html')
|
16
16
|
assert_equal 1, requests.length
|
17
17
|
end
|
18
18
|
|
@@ -29,7 +29,7 @@ class FollowMetaTest < Test::Unit::TestCase
|
|
29
29
|
requests << params[:request]
|
30
30
|
}
|
31
31
|
|
32
|
-
|
32
|
+
@agent.get('http://localhost/tc_follow_meta.html')
|
33
33
|
assert_nil requests[1]['referer']
|
34
34
|
end
|
35
35
|
|
@@ -112,7 +112,7 @@ class FollowMetaTest < Test::Unit::TestCase
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
|
115
|
+
@agent.get('http://localhost/http_refresh?refresh_time=1')
|
116
116
|
assert_equal [1], @agent.slept
|
117
117
|
end
|
118
118
|
|
data/test/test_form_button.rb
CHANGED
@@ -21,6 +21,14 @@ class TestFormButtons < Test::Unit::TestCase
|
|
21
21
|
assert_form_contains_button('<button type="button" value="submit"/>')
|
22
22
|
end
|
23
23
|
|
24
|
+
def test_image_button_tag
|
25
|
+
assert_form_contains_button('<input type="image" name="submit" src="http://foo.com/image.jpg"/>')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_no_name_image_button_tag
|
29
|
+
assert_form_contains_button('<input type="image" src="http://foo.com/image.jpg"/>')
|
30
|
+
end
|
31
|
+
|
24
32
|
def assert_form_contains_button(button)
|
25
33
|
page = Mechanize::Page.new(nil, html_response, html(button), 200, @agent)
|
26
34
|
assert_equal(1, page.forms.length)
|