mechanize 0.4.4 → 0.4.5
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 +10 -0
- data/EXAMPLES +43 -0
- data/NOTES +15 -0
- data/lib/mechanize.rb +12 -7
- data/lib/mechanize/cookie.rb +39 -7
- data/lib/mechanize/form.rb +7 -17
- data/lib/mechanize/form_elements.rb +5 -5
- data/lib/mechanize/mech_version.rb +1 -1
- data/lib/mechanize/page.rb +15 -8
- data/test/README +3 -3
- data/test/htdocs/file_upload.html +2 -0
- data/test/htdocs/form_multival.html +37 -0
- data/test/htdocs/form_test.html +2 -0
- data/test/server.rb +1 -0
- data/test/servlets.rb +17 -2
- data/test/tc_cookie_class.rb +209 -0
- data/test/tc_cookie_jar.rb +167 -0
- data/test/tc_cookies.rb +11 -0
- data/test/tc_filter.rb +34 -0
- data/test/tc_forms.rb +43 -1
- data/test/ts_mech.rb +3 -0
- metadata +78 -76
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 0.4.5
|
2
|
+
|
3
|
+
* Added support for multiple values of the same name
|
4
|
+
* Updated build_query_string to take an array of arrays (Thanks Michal Janeczek)
|
5
|
+
* Added WWW::Mechanize#body_filter= so that response bodies can be preprocessed
|
6
|
+
* Added WWW::Page#body_filter= so that response bodies can be preprocessed
|
7
|
+
* Added support for more date formats in the cookie parser
|
8
|
+
* Fixed a bug with empty select lists
|
9
|
+
* Fixing a problem with cookies not handling no spaces after semicolons
|
10
|
+
|
1
11
|
== 0.4.4
|
2
12
|
|
3
13
|
* Fixed error in method signature, basic_authetication is now basic_auth
|
data/EXAMPLES
CHANGED
@@ -53,3 +53,46 @@ This example uploads one image as two different images to flickr.
|
|
53
53
|
|
54
54
|
agent.submit(form)
|
55
55
|
|
56
|
+
== Page Body Filter
|
57
|
+
This example shows how to preprocess a body before mechanize parses it. The
|
58
|
+
body filter sends the page body to the code block, and parses what the code
|
59
|
+
block returns. The filter on WWW::Page#body_filter is a "per-page" filter,
|
60
|
+
meaning that it is only applied to one page object.
|
61
|
+
|
62
|
+
require 'rubygems'
|
63
|
+
require 'mechanize'
|
64
|
+
|
65
|
+
agent = WWW::Mechanize.new
|
66
|
+
|
67
|
+
page = agent.get('http://google.com/')
|
68
|
+
page.body_filter = lambda { |body|
|
69
|
+
body.gsub(/google/i, "Net::DAAP::Client")
|
70
|
+
}
|
71
|
+
puts page.body
|
72
|
+
|
73
|
+
page = agent.get('http://google.com/')
|
74
|
+
puts page.body
|
75
|
+
|
76
|
+
== Global Body Filter
|
77
|
+
The body filter can be set on the WWW::Mechanize object for use as a global
|
78
|
+
filter. The filter set will be applied to every page that is requested. The
|
79
|
+
following example shows the global filter being used, then being set back to
|
80
|
+
the original filter.
|
81
|
+
|
82
|
+
require 'rubygems'
|
83
|
+
require 'mechanize'
|
84
|
+
|
85
|
+
agent = WWW::Mechanize.new
|
86
|
+
|
87
|
+
old_filter = agent.body_filter
|
88
|
+
agent.body_filter = lambda { |body|
|
89
|
+
body.gsub(/(<a[^>]*>)[^<]*(<\/a[^>]*>)/i, "#{$1}Net::DAAP::Client#{$2}")
|
90
|
+
}
|
91
|
+
|
92
|
+
page = agent.get('http://google.com/')
|
93
|
+
page.links.each { |l| puts l.text }
|
94
|
+
|
95
|
+
agent.body_filter = old_filter
|
96
|
+
page = agent.get('http://google.com/')
|
97
|
+
page.links.each { |l| puts l.text }
|
98
|
+
|
data/NOTES
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
= Mechanize Release Notes
|
2
2
|
|
3
|
+
== 0.4.5
|
4
|
+
|
5
|
+
This release comes with a new filtering system. You can now manipulate the
|
6
|
+
response body before mechanize parses it. This can be useful if you know that
|
7
|
+
the HTML you need to parse is broken, or if you want to speed up the parsing.
|
8
|
+
This filter can be done on a global basis, or on a per page basis. Check out
|
9
|
+
the new examples in the EXAMPLES file for usage.
|
10
|
+
|
11
|
+
This release is also starting to phase out the misspelled method
|
12
|
+
WWW::Mechanize#basic_authetication. If you are using that method, please
|
13
|
+
switch to WWW::Mechanize#basic_auth.
|
14
|
+
|
15
|
+
The 0.4.5 release has many bug fixes, most noteably better cookie parsing and
|
16
|
+
better form support.
|
17
|
+
|
3
18
|
== 0.4.4
|
4
19
|
|
5
20
|
This release of mechanize comes with a new "Option" object that can be
|
data/lib/mechanize.rb
CHANGED
@@ -73,6 +73,7 @@ class Mechanize
|
|
73
73
|
attr_accessor :watch_for_set
|
74
74
|
attr_accessor :max_history
|
75
75
|
attr_accessor :ca_file
|
76
|
+
attr_accessor :body_filter
|
76
77
|
attr_reader :history
|
77
78
|
|
78
79
|
def initialize
|
@@ -83,6 +84,7 @@ class Mechanize
|
|
83
84
|
@read_timeout = nil
|
84
85
|
@watch_for_set = nil
|
85
86
|
@max_history = nil
|
87
|
+
@body_filter = lambda { |body| body }
|
86
88
|
@cookie_jar = CookieJar.new
|
87
89
|
@log = Logger.new(nil)
|
88
90
|
yield self if block_given?
|
@@ -107,7 +109,10 @@ class Mechanize
|
|
107
109
|
@password = password
|
108
110
|
end
|
109
111
|
|
110
|
-
|
112
|
+
def basic_authetication(user, password)
|
113
|
+
$stderr.puts "This method will be deprecated, please change to 'basic_auth'"
|
114
|
+
basic_auth(user, password)
|
115
|
+
end
|
111
116
|
|
112
117
|
def get(url)
|
113
118
|
cur_page = current_page() || Page.new
|
@@ -121,7 +126,7 @@ class Mechanize
|
|
121
126
|
def post(url, query={})
|
122
127
|
cur_page = current_page() || Page.new
|
123
128
|
|
124
|
-
request_data = [build_query_string(query)]
|
129
|
+
request_data = [WWW::Mechanize.build_query_string(query)]
|
125
130
|
|
126
131
|
# this is called before the request is sent
|
127
132
|
pre_request_hook = proc {|request|
|
@@ -155,9 +160,9 @@ class Mechanize
|
|
155
160
|
post_form(uri, form)
|
156
161
|
when 'GET'
|
157
162
|
if uri.query.nil?
|
158
|
-
get(uri.to_s + "?" + build_query_string(query))
|
163
|
+
get(uri.to_s + "?" + WWW::Mechanize.build_query_string(query))
|
159
164
|
else
|
160
|
-
get(uri.to_s + "&" + build_query_string(query))
|
165
|
+
get(uri.to_s + "&" + WWW::Mechanize.build_query_string(query))
|
161
166
|
end
|
162
167
|
else
|
163
168
|
raise 'unsupported method'
|
@@ -290,7 +295,7 @@ class Mechanize
|
|
290
295
|
page.code = response.code
|
291
296
|
|
292
297
|
response.read_body
|
293
|
-
page.body = response.body
|
298
|
+
page.body = body_filter.call(response.body)
|
294
299
|
|
295
300
|
log.info("status: #{ page.code }")
|
296
301
|
|
@@ -309,9 +314,9 @@ class Mechanize
|
|
309
314
|
}
|
310
315
|
end
|
311
316
|
|
312
|
-
def build_query_string(
|
317
|
+
def self.build_query_string(parameters)
|
313
318
|
vals = []
|
314
|
-
|
319
|
+
parameters.each { |k,v|
|
315
320
|
vals <<
|
316
321
|
[WEBrick::HTTPUtils.escape_form(k),
|
317
322
|
WEBrick::HTTPUtils.escape_form(v)].join("=")
|
data/lib/mechanize/cookie.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
module WWW
|
2
4
|
class Cookie
|
3
5
|
attr_reader :name, :value, :path, :domain, :expires, :secure
|
@@ -8,7 +10,7 @@ module WWW
|
|
8
10
|
@domain = cookie[:domain]
|
9
11
|
@expires = cookie[:expires]
|
10
12
|
@secure = cookie[:secure]
|
11
|
-
@string = "#{cookie[:name]}=#{
|
13
|
+
@string = "#{cookie[:name]}=#{cookie[:value]}"
|
12
14
|
end
|
13
15
|
|
14
16
|
def Cookie::parse(uri, raw_cookie, &block)
|
@@ -16,10 +18,10 @@ module WWW
|
|
16
18
|
esc.split(/,/).each do |cookie_text|
|
17
19
|
cookie_values = Hash.new
|
18
20
|
cookie = Hash.new
|
19
|
-
cookie_text.split(/;
|
21
|
+
cookie_text.split(/; ?/).each do |data|
|
20
22
|
name, value = data.split('=', 2)
|
21
23
|
next unless name
|
22
|
-
cookie[name] = value
|
24
|
+
cookie[name] = value
|
23
25
|
end
|
24
26
|
|
25
27
|
cookie_values[:path] = cookie.delete(
|
@@ -30,18 +32,48 @@ module WWW
|
|
30
32
|
if expires_key
|
31
33
|
time = nil
|
32
34
|
expires_val = cookie.delete(expires_key)
|
35
|
+
|
36
|
+
# First lets try dates with timezones
|
33
37
|
[ '%A %d-%b-%y %T %Z',
|
34
|
-
'%a
|
35
|
-
'%a %d %b %Y %T %Z'
|
38
|
+
'%a %d-%b-%Y %T %Z',
|
39
|
+
'%a %d %b %Y %T %Z',
|
40
|
+
'%d %b %y %H:%M %Z', # 14 Apr 89 03:20 GMT
|
41
|
+
'%a %d %b %y %H:%M %Z', # Fri, 17 Mar 89 4:01 GMT
|
42
|
+
'%a %b %d %H:%M %Z %Y', # Mon Jan 16 16:12 PDT 1989
|
43
|
+
'%d %b %Y %H:%M-%Z (%A)', # 6 May 1992 16:41-JST (Wednesday)
|
44
|
+
'%y-%m-%d %T %Z', # 95-06-08 19:32:48 EDT
|
36
45
|
].each { |fmt|
|
37
46
|
begin
|
38
47
|
time = DateTime.strptime(expires_val, fmt)
|
39
|
-
rescue ArgumentError
|
48
|
+
rescue ArgumentError => er
|
40
49
|
else
|
41
50
|
break
|
42
51
|
end
|
43
52
|
}
|
44
|
-
|
53
|
+
|
54
|
+
# If it didn't have a timezone, we'll assume GMT, like Mozilla does
|
55
|
+
if time.nil?
|
56
|
+
[
|
57
|
+
'%d %b %y %T %Z', # 14 Apr 89 03:20:12
|
58
|
+
'%a %d %b %y %T %Z', # Fri, 17 Mar 89 4:01:33
|
59
|
+
#'%d-%b-%Y %H:%M:%S.%N %Z', # 22-AUG-1993 10:59:12.82
|
60
|
+
'%d-%b-%Y %H:%M%P %Z', # 22-AUG-1993 10:59pm
|
61
|
+
'%d-%b-%Y %H:%M %p %Z', # 22-AUG-1993 12:59 PM
|
62
|
+
#'%A %B %d %Y %H:%M %p', # Friday, August 04, 1995 3:54 PM
|
63
|
+
'%x %I:%M:%S %p %Z', # 06/21/95 04:24:34 PM
|
64
|
+
'%d/%m/%y %H:%M %Z', # 20/06/95 21:07
|
65
|
+
].each { |fmt|
|
66
|
+
begin
|
67
|
+
time = DateTime.strptime("#{expires_val} GMT", fmt)
|
68
|
+
rescue ArgumentError => er
|
69
|
+
else
|
70
|
+
break
|
71
|
+
end
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
# If we couldn't parse it, set it to the current time
|
76
|
+
time = DateTime.now if time == nil
|
45
77
|
cookie_values[:expires] = time
|
46
78
|
end
|
47
79
|
|
data/lib/mechanize/form.rb
CHANGED
@@ -50,14 +50,15 @@ module WWW
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def build_query(buttons = [])
|
53
|
-
query =
|
53
|
+
query = []
|
54
54
|
|
55
55
|
fields().each do |f|
|
56
|
-
|
56
|
+
next unless f.value
|
57
|
+
query << [f.name, f.value]
|
57
58
|
end
|
58
59
|
|
59
60
|
checkboxes().each do |f|
|
60
|
-
query[f.name
|
61
|
+
query << [f.name, f.value || "on"] if f.checked
|
61
62
|
end
|
62
63
|
|
63
64
|
radio_groups = {}
|
@@ -72,7 +73,7 @@ module WWW
|
|
72
73
|
|
73
74
|
if checked.size == 1
|
74
75
|
f = checked.first
|
75
|
-
query[f.name
|
76
|
+
query << [f.name, f.value || ""]
|
76
77
|
elsif checked.size > 1
|
77
78
|
raise "multiple radiobuttons are checked in the same group!"
|
78
79
|
end
|
@@ -102,7 +103,7 @@ module WWW
|
|
102
103
|
query = params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
|
103
104
|
"--#{boundary}--\r\n"
|
104
105
|
else
|
105
|
-
query = build_query_string(query_params)
|
106
|
+
query = WWW::Mechanize.build_query_string(query_params)
|
106
107
|
end
|
107
108
|
|
108
109
|
query
|
@@ -120,7 +121,7 @@ module WWW
|
|
120
121
|
when 'input'
|
121
122
|
case (node.attributes['type'] || 'text').downcase
|
122
123
|
when 'text', 'password', 'hidden', 'int'
|
123
|
-
@fields << Field.new(node.attributes['name'], node.attributes['value'])
|
124
|
+
@fields << Field.new(node.attributes['name'], node.attributes['value'] || '')
|
124
125
|
when 'radio'
|
125
126
|
@radiobuttons << RadioButton.new(node.attributes['name'], node.attributes['value'], node.attributes.has_key?('checked'))
|
126
127
|
when 'checkbox'
|
@@ -171,17 +172,6 @@ module WWW
|
|
171
172
|
|
172
173
|
body
|
173
174
|
end
|
174
|
-
|
175
|
-
def build_query_string(hash)
|
176
|
-
vals = []
|
177
|
-
hash.each_pair do |k,v|
|
178
|
-
vals << [
|
179
|
-
WEBrick::HTTPUtils.escape_form(k),
|
180
|
-
WEBrick::HTTPUtils.escape_form(v)
|
181
|
-
].join("=")
|
182
|
-
end
|
183
|
-
vals.join("&")
|
184
|
-
end
|
185
175
|
end
|
186
176
|
|
187
177
|
class Form < GlobalForm
|
@@ -41,7 +41,7 @@ module WWW
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def add_to_query(query)
|
44
|
-
query[@name
|
44
|
+
query << [@name, @value || ''] if @name
|
45
45
|
end
|
46
46
|
|
47
47
|
# Returns an array of Button objects
|
@@ -62,9 +62,9 @@ module WWW
|
|
62
62
|
|
63
63
|
def add_to_query(query)
|
64
64
|
if @name
|
65
|
-
query[@name
|
66
|
-
query[@name+".x"
|
67
|
-
query[@name+".y"
|
65
|
+
query << [@name, @value || '']
|
66
|
+
query << [@name + ".x", (@x || 0).to_s]
|
67
|
+
query << [@name + ".y", (@y || 0).to_s]
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -101,7 +101,7 @@ module WWW
|
|
101
101
|
@value = option.value if option.selected
|
102
102
|
end
|
103
103
|
}
|
104
|
-
@value = @options.first.value if @value == nil
|
104
|
+
@value = @options.first.value if (@value == nil && @options.first)
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
data/lib/mechanize/page.rb
CHANGED
@@ -22,6 +22,7 @@ module WWW
|
|
22
22
|
class Page
|
23
23
|
attr_accessor :uri, :cookies, :response, :body, :code, :watch_for_set
|
24
24
|
attr_finder :frames, :iframes, :links, :forms, :meta, :watches
|
25
|
+
attr_reader :body_filter
|
25
26
|
|
26
27
|
# Alias our finders so that we can lazily parse the html
|
27
28
|
alias :find_frames :frames
|
@@ -33,15 +34,21 @@ module WWW
|
|
33
34
|
|
34
35
|
def initialize(uri=nil, cookies=[], response=nil, body=nil, code=nil)
|
35
36
|
@uri, @cookies, @response, @body, @code = uri, cookies, response, body, code
|
36
|
-
@frames
|
37
|
-
@iframes
|
38
|
-
@links
|
39
|
-
@forms
|
40
|
-
@meta
|
41
|
-
@watches
|
42
|
-
@root
|
37
|
+
@frames = nil
|
38
|
+
@iframes = nil
|
39
|
+
@links = nil
|
40
|
+
@forms = nil
|
41
|
+
@meta = nil
|
42
|
+
@watches = nil
|
43
|
+
@root = nil
|
44
|
+
@body_filter = lambda { |body| body }
|
43
45
|
end
|
44
46
|
|
47
|
+
def body_filter=(filter)
|
48
|
+
@body_filter = filter
|
49
|
+
parse_html()
|
50
|
+
end
|
51
|
+
|
45
52
|
def header
|
46
53
|
@response.header
|
47
54
|
end
|
@@ -96,7 +103,7 @@ module WWW
|
|
96
103
|
# construct parser and feed with HTML
|
97
104
|
parser = HTMLTree::XMLParser.new
|
98
105
|
begin
|
99
|
-
parser.feed(@body)
|
106
|
+
parser.feed(body_filter.call(@body))
|
100
107
|
rescue => ex
|
101
108
|
if ex.message =~ /attempted adding second root element to document/ and
|
102
109
|
# Put the whole document inside a single root element, which I simply name
|
data/test/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Mechanize Testing
|
2
2
|
|
3
|
-
|
4
|
-
execute: 'server.rb'
|
3
|
+
To run the tests, execute ts_mech.rb
|
5
4
|
|
6
|
-
|
5
|
+
ts_mech.rb spawns a thread that has a WEBrick server in it to test against.
|
6
|
+
The WEBrick server can be found in server.rb.
|
7
7
|
|
@@ -8,6 +8,8 @@
|
|
8
8
|
Your name: <input type="text" name="name" /><br />
|
9
9
|
File to process: <input name="userfile1" type="file" /><br />
|
10
10
|
<input type="text" name="foo[aaron]" value="test" />
|
11
|
+
<select name="foo">
|
12
|
+
</select>
|
11
13
|
<input type="submit" value="Send File" />
|
12
14
|
</form>
|
13
15
|
<form enctype="multipart/form-data" action="/file_upload" method="post">
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<html>
|
2
|
+
<head><title>Page Title</title></head>
|
3
|
+
<body>
|
4
|
+
<form name="post_form" method="post" action="/form_post">
|
5
|
+
<table>
|
6
|
+
<tr>
|
7
|
+
<td>First Name</td>
|
8
|
+
<td><input name="first" type="text" /></td>
|
9
|
+
</tr>
|
10
|
+
<tr>
|
11
|
+
<td>First Name Again</td>
|
12
|
+
<td><input name="first" type="text" /></td>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<td><input type="submit" value="Submit" /></td>
|
16
|
+
<td></td>
|
17
|
+
</tr>
|
18
|
+
</table>
|
19
|
+
</form>
|
20
|
+
<form name="get_form" method="get" action="/form_post">
|
21
|
+
<table>
|
22
|
+
<tr>
|
23
|
+
<td>First Name</td>
|
24
|
+
<td><input name="first" type="text" /></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<td>First Name Again</td>
|
28
|
+
<td><input name="first" type="text" /></td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<td><input type="submit" value="Submit" /></td>
|
32
|
+
<td></td>
|
33
|
+
</tr>
|
34
|
+
</table>
|
35
|
+
</form>
|
36
|
+
</body>
|
37
|
+
</html>
|
data/test/htdocs/form_test.html
CHANGED
data/test/server.rb
CHANGED
@@ -11,6 +11,7 @@ s = WEBrick::HTTPServer.new(
|
|
11
11
|
:AccessLog => Logger.new(nil)
|
12
12
|
)
|
13
13
|
s.mount("/one_cookie", OneCookieTest)
|
14
|
+
s.mount("/one_cookie_no_space", OneCookieNoSpacesTest)
|
14
15
|
s.mount("/many_cookies", ManyCookiesTest)
|
15
16
|
s.mount("/many_cookies_as_string", ManyCookiesAsStringTest)
|
16
17
|
s.mount("/send_cookies", SendCookiesTest)
|
data/test/servlets.rb
CHANGED
@@ -28,7 +28,9 @@ class FormTest < WEBrick::HTTPServlet::AbstractServlet
|
|
28
28
|
def do_GET(req, res)
|
29
29
|
res.body = "<HTML><body>"
|
30
30
|
req.query.each_key { |k|
|
31
|
-
|
31
|
+
req.query[k].each_data { |data|
|
32
|
+
res.body << "<a href=\"#\">#{k}:#{data}</a><br />"
|
33
|
+
}
|
32
34
|
}
|
33
35
|
res.body << "</body></HTML>"
|
34
36
|
res['Content-Type'] = "text/html"
|
@@ -37,7 +39,9 @@ class FormTest < WEBrick::HTTPServlet::AbstractServlet
|
|
37
39
|
def do_POST(req, res)
|
38
40
|
res.body = "<HTML><body>"
|
39
41
|
req.query.each_key { |k|
|
40
|
-
|
42
|
+
req.query[k].each_data { |data|
|
43
|
+
res.body << "<a href=\"#\">#{k}:#{data}</a><br />"
|
44
|
+
}
|
41
45
|
}
|
42
46
|
res.body << "</body></HTML>"
|
43
47
|
res['Content-Type'] = "text/html"
|
@@ -55,6 +59,17 @@ class OneCookieTest < WEBrick::HTTPServlet::AbstractServlet
|
|
55
59
|
end
|
56
60
|
end
|
57
61
|
|
62
|
+
class OneCookieNoSpacesTest < WEBrick::HTTPServlet::AbstractServlet
|
63
|
+
def do_GET(req, res)
|
64
|
+
cookie = WEBrick::Cookie.new("foo", "bar")
|
65
|
+
cookie.path = "/"
|
66
|
+
cookie.expires = Time.now + 86400
|
67
|
+
res.cookies << cookie.to_s.gsub(/; /, ';')
|
68
|
+
res['Content-Type'] = "text/html"
|
69
|
+
res.body = "<html><body>hello</body></html>"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
58
73
|
class ManyCookiesTest < WEBrick::HTTPServlet::AbstractServlet
|
59
74
|
def do_GET(req, res)
|
60
75
|
name_cookie = WEBrick::Cookie.new("name", "Aaron")
|
@@ -0,0 +1,209 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'mechanize/cookie'
|
5
|
+
require 'uri'
|
6
|
+
require 'test_includes'
|
7
|
+
|
8
|
+
module Enumerable
|
9
|
+
def combine
|
10
|
+
masks = inject([[], 1]){|(ar, m), e| [ar<<m, m<<1]}[0]
|
11
|
+
all = masks.inject(0){|al, m| al|m}
|
12
|
+
|
13
|
+
result = []
|
14
|
+
for i in 1..all do
|
15
|
+
tmp = []
|
16
|
+
each_with_index do |e, idx|
|
17
|
+
tmp << e unless (masks[idx] & i) == 0
|
18
|
+
end
|
19
|
+
result << tmp
|
20
|
+
end
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CookieClassTest < Test::Unit::TestCase
|
26
|
+
def test_parse_dates
|
27
|
+
url = URI.parse('http://localhost/')
|
28
|
+
|
29
|
+
yesterday = DateTime.now - 1
|
30
|
+
|
31
|
+
dates = [ "14 Apr 89 03:20:12",
|
32
|
+
"14 Apr 89 03:20 GMT",
|
33
|
+
"Fri, 17 Mar 89 4:01:33",
|
34
|
+
"Fri, 17 Mar 89 4:01 GMT",
|
35
|
+
"Mon Jan 16 16:12 PDT 1989",
|
36
|
+
"Mon Jan 16 16:12 +0130 1989",
|
37
|
+
"6 May 1992 16:41-JST (Wednesday)",
|
38
|
+
#"22-AUG-1993 10:59:12.82",
|
39
|
+
"22-AUG-1993 10:59pm",
|
40
|
+
"22-AUG-1993 12:59am",
|
41
|
+
"22-AUG-1993 12:59 PM",
|
42
|
+
#"Friday, August 04, 1995 3:54 PM",
|
43
|
+
"06/21/95 04:24:34 PM",
|
44
|
+
"20/06/95 21:07",
|
45
|
+
"95-06-08 19:32:48 EDT",
|
46
|
+
]
|
47
|
+
|
48
|
+
dates.each do |date|
|
49
|
+
cookie = "PREF=1; expires=#{date}"
|
50
|
+
WWW::Cookie.parse(url, cookie) { |cookie|
|
51
|
+
assert_equal(true, cookie.expires < yesterday)
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_parse_valid_cookie
|
57
|
+
url = URI.parse('http://rubyforge.org/')
|
58
|
+
cookie_params = {}
|
59
|
+
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
60
|
+
cookie_params['path'] = 'path=/'
|
61
|
+
cookie_params['domain'] = 'domain=.rubyforge.org'
|
62
|
+
cookie_params['httponly'] = 'HttpOnly'
|
63
|
+
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
64
|
+
|
65
|
+
expires = DateTime.strptime('Sun, 27-Sep-2037 00:00:00 GMT',
|
66
|
+
'%a, %d-%b-%Y %T %Z')
|
67
|
+
|
68
|
+
cookie_params.keys.combine.each do |c|
|
69
|
+
cookie_text = "#{cookie_value}; "
|
70
|
+
c.each_with_index do |key, idx|
|
71
|
+
if idx == (c.length - 1)
|
72
|
+
cookie_text << "#{cookie_params[key]}"
|
73
|
+
else
|
74
|
+
cookie_text << "#{cookie_params[key]}; "
|
75
|
+
end
|
76
|
+
end
|
77
|
+
cookie = nil
|
78
|
+
WWW::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
|
79
|
+
assert_not_nil(cookie)
|
80
|
+
assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
|
81
|
+
assert_equal('/', cookie.path)
|
82
|
+
assert_equal('rubyforge.org', cookie.domain)
|
83
|
+
|
84
|
+
# if expires was set, make sure we parsed it
|
85
|
+
if c.find { |k| k == 'expires' }
|
86
|
+
assert_equal(expires, cookie.expires)
|
87
|
+
else
|
88
|
+
assert_nil(cookie.expires)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# If no path was given, use the one from the URL
|
94
|
+
def test_cookie_using_url_path
|
95
|
+
url = URI.parse('http://rubyforge.org/login')
|
96
|
+
cookie_params = {}
|
97
|
+
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
98
|
+
cookie_params['path'] = 'path=/'
|
99
|
+
cookie_params['domain'] = 'domain=.rubyforge.org'
|
100
|
+
cookie_params['httponly'] = 'HttpOnly'
|
101
|
+
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
102
|
+
|
103
|
+
expires = DateTime.strptime('Sun, 27-Sep-2037 00:00:00 GMT',
|
104
|
+
'%a, %d-%b-%Y %T %Z')
|
105
|
+
|
106
|
+
cookie_params.keys.combine.each do |c|
|
107
|
+
next if c.find { |k| k == 'path' }
|
108
|
+
cookie_text = "#{cookie_value}; "
|
109
|
+
c.each_with_index do |key, idx|
|
110
|
+
if idx == (c.length - 1)
|
111
|
+
cookie_text << "#{cookie_params[key]}"
|
112
|
+
else
|
113
|
+
cookie_text << "#{cookie_params[key]}; "
|
114
|
+
end
|
115
|
+
end
|
116
|
+
cookie = nil
|
117
|
+
WWW::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
|
118
|
+
assert_not_nil(cookie)
|
119
|
+
assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
|
120
|
+
assert_equal('rubyforge.org', cookie.domain)
|
121
|
+
assert_equal('/login', cookie.path)
|
122
|
+
|
123
|
+
# if expires was set, make sure we parsed it
|
124
|
+
if c.find { |k| k == 'expires' }
|
125
|
+
assert_equal(expires, cookie.expires)
|
126
|
+
else
|
127
|
+
assert_nil(cookie.expires)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# If no domain was given, we must use the one from the URL
|
133
|
+
def test_cookie_with_url_domain
|
134
|
+
url = URI.parse('http://login.rubyforge.org/')
|
135
|
+
cookie_params = {}
|
136
|
+
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
137
|
+
cookie_params['path'] = 'path=/'
|
138
|
+
cookie_params['domain'] = 'domain=.rubyforge.org'
|
139
|
+
cookie_params['httponly'] = 'HttpOnly'
|
140
|
+
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
141
|
+
|
142
|
+
expires = DateTime.strptime('Sun, 27-Sep-2037 00:00:00 GMT',
|
143
|
+
'%a, %d-%b-%Y %T %Z')
|
144
|
+
|
145
|
+
cookie_params.keys.combine.each do |c|
|
146
|
+
next if c.find { |k| k == 'domain' }
|
147
|
+
cookie_text = "#{cookie_value}; "
|
148
|
+
c.each_with_index do |key, idx|
|
149
|
+
if idx == (c.length - 1)
|
150
|
+
cookie_text << "#{cookie_params[key]}"
|
151
|
+
else
|
152
|
+
cookie_text << "#{cookie_params[key]}; "
|
153
|
+
end
|
154
|
+
end
|
155
|
+
cookie = nil
|
156
|
+
WWW::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
|
157
|
+
assert_not_nil(cookie)
|
158
|
+
assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
|
159
|
+
assert_equal('/', cookie.path)
|
160
|
+
|
161
|
+
assert_equal('login.rubyforge.org', cookie.domain)
|
162
|
+
|
163
|
+
# if expires was set, make sure we parsed it
|
164
|
+
if c.find { |k| k == 'expires' }
|
165
|
+
assert_equal(expires, cookie.expires)
|
166
|
+
else
|
167
|
+
assert_nil(cookie.expires)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_parse_cookie_no_spaces
|
173
|
+
url = URI.parse('http://rubyforge.org/')
|
174
|
+
cookie_params = {}
|
175
|
+
cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
|
176
|
+
cookie_params['path'] = 'path=/'
|
177
|
+
cookie_params['domain'] = 'domain=.rubyforge.org'
|
178
|
+
cookie_params['httponly'] = 'HttpOnly'
|
179
|
+
cookie_value = '12345%7D=ASDFWEE345%3DASda'
|
180
|
+
|
181
|
+
expires = DateTime.strptime('Sun, 27-Sep-2037 00:00:00 GMT',
|
182
|
+
'%a, %d-%b-%Y %T %Z')
|
183
|
+
|
184
|
+
cookie_params.keys.combine.each do |c|
|
185
|
+
cookie_text = "#{cookie_value};"
|
186
|
+
c.each_with_index do |key, idx|
|
187
|
+
if idx == (c.length - 1)
|
188
|
+
cookie_text << "#{cookie_params[key]}"
|
189
|
+
else
|
190
|
+
cookie_text << "#{cookie_params[key]};"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
cookie = nil
|
194
|
+
WWW::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
|
195
|
+
assert_not_nil(cookie)
|
196
|
+
assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
|
197
|
+
assert_equal('/', cookie.path)
|
198
|
+
assert_equal('rubyforge.org', cookie.domain)
|
199
|
+
|
200
|
+
# if expires was set, make sure we parsed it
|
201
|
+
if c.find { |k| k == 'expires' }
|
202
|
+
assert_equal(expires, cookie.expires)
|
203
|
+
else
|
204
|
+
assert_nil(cookie.expires)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
@@ -0,0 +1,167 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'mechanize/cookie'
|
5
|
+
require 'uri'
|
6
|
+
require 'test_includes'
|
7
|
+
|
8
|
+
class CookieJarTest < Test::Unit::TestCase
|
9
|
+
def test_add_future_cookies
|
10
|
+
values = { :name => 'Foo',
|
11
|
+
:value => 'Bar',
|
12
|
+
:path => '/',
|
13
|
+
:expires => DateTime.now + 10,
|
14
|
+
:domain => 'rubyforge.org'
|
15
|
+
}
|
16
|
+
url = URI.parse('http://rubyforge.org/')
|
17
|
+
|
18
|
+
jar = WWW::CookieJar.new
|
19
|
+
assert_equal(0, jar.cookies(url).length)
|
20
|
+
|
21
|
+
# Add one cookie with an expiration date in the future
|
22
|
+
cookie = WWW::Cookie.new(values)
|
23
|
+
jar.add(cookie)
|
24
|
+
assert_equal(1, jar.cookies(url).length)
|
25
|
+
|
26
|
+
# Add the same cookie, and we should still only have one
|
27
|
+
jar.add(WWW::Cookie.new(values))
|
28
|
+
assert_equal(1, jar.cookies(url).length)
|
29
|
+
|
30
|
+
# Make sure we can get the cookie from different paths
|
31
|
+
assert_equal(1, jar.cookies(URI.parse('http://rubyforge.org/login')).length)
|
32
|
+
|
33
|
+
# Make sure we can't get the cookie from different domains
|
34
|
+
assert_equal(0, jar.cookies(URI.parse('http://google.com/')).length)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_add_multiple_cookies
|
38
|
+
values = { :name => 'Foo',
|
39
|
+
:value => 'Bar',
|
40
|
+
:path => '/',
|
41
|
+
:expires => DateTime.now + 10,
|
42
|
+
:domain => 'rubyforge.org'
|
43
|
+
}
|
44
|
+
url = URI.parse('http://rubyforge.org/')
|
45
|
+
|
46
|
+
jar = WWW::CookieJar.new
|
47
|
+
assert_equal(0, jar.cookies(url).length)
|
48
|
+
|
49
|
+
# Add one cookie with an expiration date in the future
|
50
|
+
cookie = WWW::Cookie.new(values)
|
51
|
+
jar.add(cookie)
|
52
|
+
assert_equal(1, jar.cookies(url).length)
|
53
|
+
|
54
|
+
# Add the same cookie, and we should still only have one
|
55
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz' )))
|
56
|
+
assert_equal(2, jar.cookies(url).length)
|
57
|
+
|
58
|
+
# Make sure we can get the cookie from different paths
|
59
|
+
assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length)
|
60
|
+
|
61
|
+
# Make sure we can't get the cookie from different domains
|
62
|
+
assert_equal(0, jar.cookies(URI.parse('http://google.com/')).length)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_expire_cookies
|
66
|
+
values = { :name => 'Foo',
|
67
|
+
:value => 'Bar',
|
68
|
+
:path => '/',
|
69
|
+
:expires => DateTime.now + 10,
|
70
|
+
:domain => 'rubyforge.org'
|
71
|
+
}
|
72
|
+
url = URI.parse('http://rubyforge.org/')
|
73
|
+
|
74
|
+
jar = WWW::CookieJar.new
|
75
|
+
assert_equal(0, jar.cookies(url).length)
|
76
|
+
|
77
|
+
# Add one cookie with an expiration date in the future
|
78
|
+
cookie = WWW::Cookie.new(values)
|
79
|
+
jar.add(cookie)
|
80
|
+
assert_equal(1, jar.cookies(url).length)
|
81
|
+
|
82
|
+
# Add a second cookie
|
83
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz' )))
|
84
|
+
assert_equal(2, jar.cookies(url).length)
|
85
|
+
|
86
|
+
# Make sure we can get the cookie from different paths
|
87
|
+
assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length)
|
88
|
+
|
89
|
+
# Expire the first cookie
|
90
|
+
jar.add(WWW::Cookie.new(values.merge( :expires => DateTime.now - 10)))
|
91
|
+
assert_equal(1, jar.cookies(url).length)
|
92
|
+
|
93
|
+
# Expire the second cookie
|
94
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz',
|
95
|
+
:expires => DateTime.now - 10)))
|
96
|
+
assert_equal(0, jar.cookies(url).length)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_session_cookies
|
100
|
+
values = { :name => 'Foo',
|
101
|
+
:value => 'Bar',
|
102
|
+
:path => '/',
|
103
|
+
:expires => nil,
|
104
|
+
:domain => 'rubyforge.org'
|
105
|
+
}
|
106
|
+
url = URI.parse('http://rubyforge.org/')
|
107
|
+
|
108
|
+
jar = WWW::CookieJar.new
|
109
|
+
assert_equal(0, jar.cookies(url).length)
|
110
|
+
|
111
|
+
# Add one cookie with an expiration date in the future
|
112
|
+
cookie = WWW::Cookie.new(values)
|
113
|
+
jar.add(cookie)
|
114
|
+
assert_equal(1, jar.cookies(url).length)
|
115
|
+
|
116
|
+
# Add a second cookie
|
117
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz' )))
|
118
|
+
assert_equal(2, jar.cookies(url).length)
|
119
|
+
|
120
|
+
# Make sure we can get the cookie from different paths
|
121
|
+
assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length)
|
122
|
+
|
123
|
+
# Expire the first cookie
|
124
|
+
jar.add(WWW::Cookie.new(values.merge( :expires => DateTime.now - 10)))
|
125
|
+
assert_equal(1, jar.cookies(url).length)
|
126
|
+
|
127
|
+
# Expire the second cookie
|
128
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz',
|
129
|
+
:expires => DateTime.now - 10)))
|
130
|
+
assert_equal(0, jar.cookies(url).length)
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_paths
|
134
|
+
values = { :name => 'Foo',
|
135
|
+
:value => 'Bar',
|
136
|
+
:path => '/login',
|
137
|
+
:expires => nil,
|
138
|
+
:domain => 'rubyforge.org'
|
139
|
+
}
|
140
|
+
url = URI.parse('http://rubyforge.org/login')
|
141
|
+
|
142
|
+
jar = WWW::CookieJar.new
|
143
|
+
assert_equal(0, jar.cookies(url).length)
|
144
|
+
|
145
|
+
# Add one cookie with an expiration date in the future
|
146
|
+
cookie = WWW::Cookie.new(values)
|
147
|
+
jar.add(cookie)
|
148
|
+
assert_equal(1, jar.cookies(url).length)
|
149
|
+
|
150
|
+
# Add a second cookie
|
151
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz' )))
|
152
|
+
assert_equal(2, jar.cookies(url).length)
|
153
|
+
|
154
|
+
# Make sure we don't get the cookie in a different path
|
155
|
+
assert_equal(0, jar.cookies(URI.parse('http://rubyforge.org/hello')).length)
|
156
|
+
assert_equal(0, jar.cookies(URI.parse('http://rubyforge.org/')).length)
|
157
|
+
|
158
|
+
# Expire the first cookie
|
159
|
+
jar.add(WWW::Cookie.new(values.merge( :expires => DateTime.now - 10)))
|
160
|
+
assert_equal(1, jar.cookies(url).length)
|
161
|
+
|
162
|
+
# Expire the second cookie
|
163
|
+
jar.add(WWW::Cookie.new(values.merge( :name => 'Baz',
|
164
|
+
:expires => DateTime.now - 10)))
|
165
|
+
assert_equal(0, jar.cookies(url).length)
|
166
|
+
end
|
167
|
+
end
|
data/test/tc_cookies.rb
CHANGED
@@ -19,6 +19,17 @@ class CookiesMechTest < Test::Unit::TestCase
|
|
19
19
|
assert_not_nil(page.links.find { |l| l.text == "no_expires:nope" })
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_no_space_cookies
|
23
|
+
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
24
|
+
page = agent.get("http://localhost:#{@port}/one_cookie_no_space")
|
25
|
+
assert_equal(1, agent.cookies.length)
|
26
|
+
foo_cookie = agent.cookies.find { |k| k.name == 'foo' }
|
27
|
+
assert_not_nil(foo_cookie, 'Foo cookie was nil')
|
28
|
+
assert_equal('bar', foo_cookie.value)
|
29
|
+
assert_equal('/', foo_cookie.path)
|
30
|
+
assert_equal(true, DateTime.now < foo_cookie.expires)
|
31
|
+
end
|
32
|
+
|
22
33
|
def test_many_cookies_as_string
|
23
34
|
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
24
35
|
page = agent.get("http://localhost:#{@port}/many_cookies_as_string")
|
data/test/tc_filter.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mechanize'
|
6
|
+
require 'test_includes'
|
7
|
+
|
8
|
+
class FilterTest < Test::Unit::TestCase
|
9
|
+
include TestMethods
|
10
|
+
|
11
|
+
def test_local_filter
|
12
|
+
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
13
|
+
page = agent.get("http://localhost:#{@port}/find_link.html")
|
14
|
+
page.body_filter = lambda { |body| body.gsub(/<body>/, '<body><a href="http://daapclient.rubyforge.org">Net::DAAP::Client</a>') }
|
15
|
+
assert_equal(16, page.links.length)
|
16
|
+
assert_not_nil(page.links.text('Net::DAAP::Client').first)
|
17
|
+
assert_equal(1, page.links.text('Net::DAAP::Client').length)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_global_filter
|
21
|
+
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
22
|
+
agent.body_filter = lambda { |body| body.gsub(/<body>/, '<body><a href="http://daapclient.rubyforge.org">Net::DAAP::Client</a>') }
|
23
|
+
page = agent.get("http://localhost:#{@port}/find_link.html")
|
24
|
+
assert_equal(16, page.links.length)
|
25
|
+
assert_not_nil(page.links.text('Net::DAAP::Client').first)
|
26
|
+
assert_equal(1, page.links.text('Net::DAAP::Client').length)
|
27
|
+
|
28
|
+
page = agent.get("http://localhost:#{@port}/find_link.html")
|
29
|
+
page.body_filter = lambda { |body| body.gsub(/<body>/, '<body><a href="http://daapclient.rubyforge.org">Net::DAAP::Client</a>') }
|
30
|
+
assert_equal(17, page.links.length)
|
31
|
+
assert_not_nil(page.links.text('Net::DAAP::Client').first)
|
32
|
+
assert_equal(2, page.links.text('Net::DAAP::Client').length)
|
33
|
+
end
|
34
|
+
end
|
data/test/tc_forms.rb
CHANGED
@@ -9,6 +9,48 @@ require 'test_includes'
|
|
9
9
|
class FormsMechTest < Test::Unit::TestCase
|
10
10
|
include TestMethods
|
11
11
|
|
12
|
+
# Test submitting form with two fields of the same name
|
13
|
+
def test_post_multival
|
14
|
+
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
15
|
+
page = agent.get("http://localhost:#{@port}/form_multival.html")
|
16
|
+
form = page.forms.name('post_form').first
|
17
|
+
|
18
|
+
assert_not_nil(form)
|
19
|
+
assert_equal(2, form.fields.name('first').length)
|
20
|
+
|
21
|
+
form.fields.name('first')[0].value = 'Aaron'
|
22
|
+
form.fields.name('first')[1].value = 'Patterson'
|
23
|
+
|
24
|
+
page = agent.submit(form)
|
25
|
+
|
26
|
+
assert_not_nil(page)
|
27
|
+
|
28
|
+
assert_equal(2, page.links.length)
|
29
|
+
assert_not_nil(page.links.text('first:Aaron').first)
|
30
|
+
assert_not_nil(page.links.text('first:Patterson').first)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Test submitting form with two fields of the same name
|
34
|
+
def test_get_multival
|
35
|
+
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
36
|
+
page = agent.get("http://localhost:#{@port}/form_multival.html")
|
37
|
+
form = page.forms.name('get_form').first
|
38
|
+
|
39
|
+
assert_not_nil(form)
|
40
|
+
assert_equal(2, form.fields.name('first').length)
|
41
|
+
|
42
|
+
form.fields.name('first')[0].value = 'Aaron'
|
43
|
+
form.fields.name('first')[1].value = 'Patterson'
|
44
|
+
|
45
|
+
page = agent.submit(form)
|
46
|
+
|
47
|
+
assert_not_nil(page)
|
48
|
+
|
49
|
+
assert_equal(2, page.links.length)
|
50
|
+
assert_not_nil(page.links.text('first:Aaron').first)
|
51
|
+
assert_not_nil(page.links.text('first:Patterson').first)
|
52
|
+
end
|
53
|
+
|
12
54
|
def test_post
|
13
55
|
agent = WWW::Mechanize.new { |a| a.log = Logger.new(nil) }
|
14
56
|
page = agent.get("http://localhost:#{@port}/form_test.html")
|
@@ -17,7 +59,7 @@ class FormsMechTest < Test::Unit::TestCase
|
|
17
59
|
assert_equal("post", post_form.method.downcase)
|
18
60
|
assert_equal("/form_post", post_form.action)
|
19
61
|
|
20
|
-
assert_equal(
|
62
|
+
assert_equal(3, post_form.fields.size)
|
21
63
|
|
22
64
|
assert_equal(1, post_form.buttons.size)
|
23
65
|
assert_equal(2, post_form.radiobuttons.size)
|
data/test/ts_mech.rb
CHANGED
metadata
CHANGED
@@ -3,11 +3,11 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: mechanize
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
7
|
-
date: 2006-05-
|
6
|
+
version: 0.4.5
|
7
|
+
date: 2006-05-20 00:00:00 -07:00
|
8
8
|
summary: Mechanize provides automated web-browsing
|
9
9
|
require_paths:
|
10
|
-
- lib
|
10
|
+
- lib
|
11
11
|
email: aaronp@rubyforge.org
|
12
12
|
homepage: mechanize.rubyforge.org
|
13
13
|
rubyforge_project: mechanize
|
@@ -18,89 +18,91 @@ bindir: bin
|
|
18
18
|
has_rdoc: true
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
24
25
|
version:
|
25
26
|
platform: ruby
|
26
27
|
signing_key:
|
27
28
|
cert_chain:
|
28
29
|
authors:
|
29
|
-
- Aaron Patterson
|
30
|
+
- Aaron Patterson
|
30
31
|
files:
|
31
|
-
- test/
|
32
|
-
- test/
|
33
|
-
- test/
|
34
|
-
- test/
|
35
|
-
- test/
|
36
|
-
- test/
|
37
|
-
- test/
|
38
|
-
- test/
|
39
|
-
- test/
|
40
|
-
- test/
|
41
|
-
- test/
|
42
|
-
- test/
|
43
|
-
- test/
|
44
|
-
- test/tc_mech.rb
|
45
|
-
- test/
|
46
|
-
- test/
|
47
|
-
- test/
|
48
|
-
- test/
|
49
|
-
- test/
|
50
|
-
- test/
|
51
|
-
- test/
|
52
|
-
- test/
|
53
|
-
- test/htdocs/
|
54
|
-
- test/htdocs/
|
55
|
-
- test/htdocs/
|
56
|
-
- test/htdocs/
|
57
|
-
- test/
|
58
|
-
-
|
59
|
-
-
|
60
|
-
-
|
61
|
-
-
|
62
|
-
- lib/mechanize
|
63
|
-
- lib/mechanize
|
64
|
-
- lib/mechanize/
|
65
|
-
- lib/mechanize/
|
66
|
-
- lib/mechanize/form_elements.rb
|
67
|
-
- lib/mechanize/mech_version.rb
|
68
|
-
- lib/mechanize/module.rb
|
69
|
-
- lib/mechanize/net-overrides
|
70
|
-
- lib/mechanize/
|
71
|
-
- lib/mechanize/
|
72
|
-
- lib/mechanize/
|
73
|
-
-
|
74
|
-
-
|
75
|
-
-
|
76
|
-
-
|
77
|
-
-
|
32
|
+
- test/data
|
33
|
+
- test/htdocs
|
34
|
+
- test/README
|
35
|
+
- test/server.rb
|
36
|
+
- test/servlets.rb
|
37
|
+
- test/tc_authenticate.rb
|
38
|
+
- test/tc_cookie_class.rb
|
39
|
+
- test/tc_cookie_jar.rb
|
40
|
+
- test/tc_cookies.rb
|
41
|
+
- test/tc_filter.rb
|
42
|
+
- test/tc_forms.rb
|
43
|
+
- test/tc_frames.rb
|
44
|
+
- test/tc_links.rb
|
45
|
+
- test/tc_mech.rb
|
46
|
+
- test/tc_parsing.rb
|
47
|
+
- test/tc_response_code.rb
|
48
|
+
- test/tc_upload.rb
|
49
|
+
- test/tc_watches.rb
|
50
|
+
- test/test_includes.rb
|
51
|
+
- test/test_mech.rb
|
52
|
+
- test/ts_mech.rb
|
53
|
+
- test/data/htpasswd
|
54
|
+
- test/htdocs/button.jpg
|
55
|
+
- test/htdocs/file_upload.html
|
56
|
+
- test/htdocs/find_link.html
|
57
|
+
- test/htdocs/form_multival.html
|
58
|
+
- test/htdocs/form_test.html
|
59
|
+
- test/htdocs/frame_test.html
|
60
|
+
- test/htdocs/google.html
|
61
|
+
- test/htdocs/iframe_test.html
|
62
|
+
- test/htdocs/index.html
|
63
|
+
- lib/mechanize
|
64
|
+
- lib/mechanize.rb
|
65
|
+
- lib/mechanize/cookie.rb
|
66
|
+
- lib/mechanize/form.rb
|
67
|
+
- lib/mechanize/form_elements.rb
|
68
|
+
- lib/mechanize/mech_version.rb
|
69
|
+
- lib/mechanize/module.rb
|
70
|
+
- lib/mechanize/net-overrides
|
71
|
+
- lib/mechanize/page.rb
|
72
|
+
- lib/mechanize/page_elements.rb
|
73
|
+
- lib/mechanize/parsing.rb
|
74
|
+
- lib/mechanize/net-overrides/net
|
75
|
+
- lib/mechanize/net-overrides/net/http.rb
|
76
|
+
- lib/mechanize/net-overrides/net/https.rb
|
77
|
+
- lib/mechanize/net-overrides/net/protocol.rb
|
78
|
+
- README
|
79
|
+
- EXAMPLES
|
80
|
+
- CHANGELOG
|
81
|
+
- LICENSE
|
82
|
+
- NOTES
|
78
83
|
test_files: []
|
79
|
-
|
80
84
|
rdoc_options:
|
81
|
-
- --main
|
82
|
-
- README
|
83
|
-
- --title
|
84
|
-
- "'WWW::Mechanize RDoc'"
|
85
|
+
- "--main"
|
86
|
+
- README
|
87
|
+
- "--title"
|
88
|
+
- "'WWW::Mechanize RDoc'"
|
85
89
|
extra_rdoc_files:
|
86
|
-
- README
|
87
|
-
- EXAMPLES
|
88
|
-
- CHANGELOG
|
89
|
-
- LICENSE
|
90
|
-
- NOTES
|
90
|
+
- README
|
91
|
+
- EXAMPLES
|
92
|
+
- CHANGELOG
|
93
|
+
- LICENSE
|
94
|
+
- NOTES
|
91
95
|
executables: []
|
92
|
-
|
93
96
|
extensions: []
|
94
|
-
|
95
97
|
requirements: []
|
96
|
-
|
97
98
|
dependencies:
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: ruby-web
|
101
|
+
version_requirement:
|
102
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
103
|
+
requirements:
|
104
|
+
-
|
105
|
+
- ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 1.1.0
|
108
|
+
version:
|