mechanize 0.6.4 → 0.6.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.txt CHANGED
@@ -1,5 +1,20 @@
1
1
  = Mechanize CHANGELOG
2
2
 
3
+ == 0.6.5
4
+
5
+ * Copying headers to a hash to prevent memory leaks
6
+ * Speeding up page parsing
7
+ * Aliased fields to elements
8
+ * Adding If-Modified-Since header
9
+ * Added delete_field! to form. Thanks to Sava Chankov
10
+ * Updated uri escaping to support high order characters. Thanks to Henrik Nyh.
11
+ * Better handling relative URIs. Thanks to Henrik Nyh
12
+ * Now handles pipes in URLs
13
+ http://rubyforge.org/tracker/?func=detail&aid=7140&group_id=1453&atid=5709
14
+ * Now escaping html entities in form fields.
15
+ http://rubyforge.org/tracker/?func=detail&aid=7563&group_id=1453&atid=5709
16
+ * Added MSIE 7.0 user agent string
17
+
3
18
  == 0.6.4
4
19
 
5
20
  * Adding the "redirect_ok" method to Mechanize to stop mechanize from
data/Manifest.txt CHANGED
@@ -19,7 +19,6 @@ lib/mechanize/form_elements.rb
19
19
  lib/mechanize/hpricot.rb
20
20
  lib/mechanize/inspect.rb
21
21
  lib/mechanize/list.rb
22
- lib/mechanize/mech_version.rb
23
22
  lib/mechanize/net-overrides/net/http.rb
24
23
  lib/mechanize/net-overrides/net/https.rb
25
24
  lib/mechanize/net-overrides/net/protocol.rb
@@ -29,3 +28,87 @@ lib/mechanize/parsers/rexml_page.rb
29
28
  lib/mechanize/pluggable_parsers.rb
30
29
  lib/mechanize/rexml.rb
31
30
  setup.rb
31
+ test/data/htpasswd
32
+ test/data/server.crt
33
+ test/data/server.csr
34
+ test/data/server.key
35
+ test/data/server.pem
36
+ test/htdocs/alt_text.html
37
+ test/htdocs/bad_form_test.html
38
+ test/htdocs/button.jpg
39
+ test/htdocs/empty_form.html
40
+ test/htdocs/file_upload.html
41
+ test/htdocs/find_link.html
42
+ test/htdocs/form_multi_select.html
43
+ test/htdocs/form_multival.html
44
+ test/htdocs/form_no_action.html
45
+ test/htdocs/form_no_input_name.html
46
+ test/htdocs/form_select.html
47
+ test/htdocs/form_select_all.html
48
+ test/htdocs/form_select_none.html
49
+ test/htdocs/form_select_noopts.html
50
+ test/htdocs/form_set_fields.html
51
+ test/htdocs/form_test.html
52
+ test/htdocs/frame_test.html
53
+ test/htdocs/google.html
54
+ test/htdocs/iframe_test.html
55
+ test/htdocs/index.html
56
+ test/htdocs/link with space.html
57
+ test/htdocs/no_title_test.html
58
+ test/htdocs/relative/tc_relative_links.html
59
+ test/htdocs/tc_bad_links.html
60
+ test/htdocs/tc_checkboxes.html
61
+ test/htdocs/tc_encoded_links.html
62
+ test/htdocs/tc_form_action.html
63
+ test/htdocs/tc_links.html
64
+ test/htdocs/tc_no_attributes.html
65
+ test/htdocs/tc_pretty_print.html
66
+ test/htdocs/tc_radiobuttons.html
67
+ test/htdocs/tc_referer.html
68
+ test/htdocs/tc_relative_links.html
69
+ test/htdocs/tc_textarea.html
70
+ test/ssl_server.rb
71
+ test/tc_authenticate.rb
72
+ test/tc_bad_links.rb
73
+ test/tc_checkboxes.rb
74
+ test/tc_cookie_class.rb
75
+ test/tc_cookie_jar.rb
76
+ test/tc_cookies.rb
77
+ test/tc_encoded_links.rb
78
+ test/tc_errors.rb
79
+ test/tc_form_action.rb
80
+ test/tc_form_as_hash.rb
81
+ test/tc_form_button.rb
82
+ test/tc_form_no_inputname.rb
83
+ test/tc_forms.rb
84
+ test/tc_frames.rb
85
+ test/tc_gzipping.rb
86
+ test/tc_html_unscape_forms.rb
87
+ test/tc_if_modified_since.rb
88
+ test/tc_links.rb
89
+ test/tc_mech.rb
90
+ test/tc_multi_select.rb
91
+ test/tc_no_attributes.rb
92
+ test/tc_page.rb
93
+ test/tc_pluggable_parser.rb
94
+ test/tc_post_form.rb
95
+ test/tc_pretty_print.rb
96
+ test/tc_proxy.rb
97
+ test/tc_radiobutton.rb
98
+ test/tc_referer.rb
99
+ test/tc_relative_links.rb
100
+ test/tc_response_code.rb
101
+ test/tc_save_file.rb
102
+ test/tc_select.rb
103
+ test/tc_select_all.rb
104
+ test/tc_select_none.rb
105
+ test/tc_select_noopts.rb
106
+ test/tc_set_fields.rb
107
+ test/tc_ssl_server.rb
108
+ test/tc_subclass.rb
109
+ test/tc_textarea.rb
110
+ test/tc_upload.rb
111
+ test/tc_watches.rb
112
+ test/test_all.rb
113
+ test/test_includes.rb
114
+ test/test_servlets.rb
data/README.txt CHANGED
@@ -29,12 +29,22 @@ Original Code:
29
29
  Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de)
30
30
 
31
31
  New Code:
32
- Copyright (c) 2006 by Aaron Patterson (aaronp@rubyforge.org)
32
+ Copyright (c) 2007 by Aaron Patterson (aaronp@rubyforge.org)
33
33
 
34
34
  This library comes with a shameless plug for employing me
35
35
  (Aaron[http://tenderlovemaking.com/]) programming
36
36
  Ruby, my favorite language!
37
37
 
38
+ == Acknowledgments
39
+
40
+ This library was heavily influenced by its namesake in the perl world. A big
41
+ thanks goes to Andy Lester (andy@petdance.com), the author of the original
42
+ perl Mechanize which is available here[http://search.cpan.org/~petdance/WWW-Mechanize-1.20/]. Ruby Mechanize would not be around without you!
43
+
44
+ Thank you to Michael Neumann for starting the Ruby version. Thanks to everyone
45
+ who's helped out in various ways. Finally, thank you to the people using this
46
+ library!
47
+
38
48
  == License
39
49
 
40
50
  This library is distributed under the GPL. Please see the LICENSE[link://files/LICENSE_txt.html] file.
data/Rakefile CHANGED
@@ -1,64 +1,60 @@
1
1
  require 'rubygems'
2
2
  require 'hoe'
3
3
 
4
- def announce(msg='')
5
- STDERR.puts msg
6
- end
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
5
+ require 'mechanize'
6
+
7
+ class MechHoe < Hoe
8
+ def define_tasks
9
+ super
10
+
11
+ desc "Tag code"
12
+ task :tag do |p|
13
+ abort "Must supply VERSION=x.y.z" unless ENV['VERSION']
14
+ v = ENV['VERSION'].gsub(/\./, '_')
15
+
16
+ rf = RubyForge.new
17
+ user = rf.userconfig['username']
7
18
 
8
- PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
9
- PKG_NAME = 'mechanize'
10
- PKG_VERSION = '0.6.4' + PKG_BUILD
19
+ baseurl = "svn+ssh://#{user}@rubyforge.org//var/svn/#{name}"
20
+ sh "svn cp -m 'tagged REL-#{v}' . #{ baseurl }/tags/REL-#{ v }"
21
+ end
22
+
23
+ desc "Branch code"
24
+ Rake::Task.define_task("branch") do |p|
25
+ abort "Must supply VERSION=x.y.z" unless ENV['VERSION']
26
+ v = ENV['VERSION'].split(/\./)[0..1].join('_')
27
+
28
+ rf = RubyForge.new
29
+ user = rf.userconfig['username']
30
+
31
+ baseurl = "svn+ssh://#{user}@rubyforge.org/var/svn/#{name}"
32
+ sh "svn cp -m'branched #{v}' #{baseurl}/trunk #{baseurl}/branches/RB-#{v}"
33
+ end
34
+
35
+ desc "Update SSL Certificate"
36
+ Rake::Task.define_task('ssl_cert') do |p|
37
+ sh "openssl genrsa -des3 -out server.key 1024"
38
+ sh "openssl req -new -key server.key -out server.csr"
39
+ sh "cp server.key server.key.org"
40
+ sh "openssl rsa -in server.key.org -out server.key"
41
+ sh "openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt"
42
+ sh "cp server.key server.pem"
43
+ sh "mv server.key server.csr server.crt server.pem test/data/"
44
+ sh "rm server.key.org"
45
+ end
46
+ end
47
+ end
11
48
 
12
- Hoe.new(PKG_NAME, PKG_VERSION) do |p|
13
- p.rubyforge_name = PKG_NAME
49
+ MechHoe.new('mechanize', WWW::Mechanize::VERSION) do |p|
50
+ p.rubyforge_name = 'mechanize'
14
51
  p.author = 'Aaron Patterson'
15
52
  p.email = 'aaronp@rubyforge.org'
16
53
  p.summary = "Mechanize provides automated web-browsing"
17
54
  p.description = p.paragraphs_of('README.txt', 3).join("\n\n")
18
55
  p.url = p.paragraphs_of('README.txt', 1).first.strip
19
56
  p.changes = p.paragraphs_of('CHANGELOG.txt', 0..2).join("\n\n")
20
- files =
21
- (p.test_globs + ['test/**/tc_*.rb',
22
- "test/htdocs/**/*.{html,jpg}",
23
- 'test/data/server.*']).map { |x|
24
- Dir.glob(x)
25
- }.flatten + ['test/data/htpasswd']
26
57
  p.extra_deps = ['hpricot']
27
- p.spec_extras = { :test_files => files }
28
- end
29
-
30
- task :update_version do
31
- announce "Updating Mechanize Version to #{PKG_VERSION}"
32
- File.open("lib/mechanize/mech_version.rb", "w") do |f|
33
- f.puts "module WWW"
34
- f.puts " class Mechanize"
35
- f.puts " Version = '#{PKG_VERSION}'"
36
- f.puts " end"
37
- f.puts "end"
38
- end
39
- sh 'svn commit -m"updating version" lib/mechanize/mech_version.rb'
40
58
  end
41
59
 
42
- desc "Tag code"
43
- Rake::Task.define_task("tag") do |p|
44
- baseurl = "svn+ssh://#{ENV['USER']}@rubyforge.org//var/svn/#{PKG_NAME}"
45
- sh "svn cp -m 'tagged #{ PKG_VERSION }' . #{ baseurl }/tags/REL-#{ PKG_VERSION }"
46
- end
47
-
48
- desc "Branch code"
49
- Rake::Task.define_task("branch") do |p|
50
- baseurl = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/#{PKG_NAME}"
51
- sh "svn cp -m 'branched #{ PKG_VERSION }' #{baseurl}/trunk #{ baseurl }/branches/RB-#{ PKG_VERSION }"
52
- end
53
60
 
54
- desc "Update SSL Certificate"
55
- Rake::Task.define_task('ssl_cert') do |p|
56
- sh "openssl genrsa -des3 -out server.key 1024"
57
- sh "openssl req -new -key server.key -out server.csr"
58
- sh "cp server.key server.key.org"
59
- sh "openssl rsa -in server.key.org -out server.key"
60
- sh "openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt"
61
- sh "cp server.key server.pem"
62
- sh "mv server.key server.csr server.crt server.pem test/data/"
63
- sh "rm server.key.org"
64
- end
data/lib/mechanize.rb CHANGED
@@ -11,15 +11,24 @@
11
11
  unless RUBY_VERSION > "1.8.2"
12
12
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "mechanize", "net-overrides")
13
13
  end
14
+
14
15
  require 'net/http'
15
16
  require 'net/https'
16
17
 
18
+ # Monkey patch for ruby 1.8.4
19
+ unless RUBY_VERSION > "1.8.4"
20
+ module Net # :nodoc:
21
+ class HTTPResponse # :nodoc:
22
+ CODE_TO_OBJ['500'] = HTTPInternalServerError
23
+ end
24
+ end
25
+ end
26
+
17
27
  require 'uri'
18
28
  require 'webrick/httputils'
19
29
  require 'zlib'
20
30
  require 'stringio'
21
31
  require 'mechanize/hpricot'
22
- require 'mechanize/mech_version'
23
32
  require 'mechanize/cookie'
24
33
  require 'mechanize/errors'
25
34
  require 'mechanize/pluggable_parsers'
@@ -50,15 +59,23 @@ module WWW
50
59
  # search_results = agent.submit(search_form)
51
60
  # puts search_results.body
52
61
  class Mechanize
62
+ ##
63
+ # The version of Mechanize you are using.
64
+
65
+ VERSION = '0.6.5'
66
+
67
+ ##
68
+ # User Agent aliases
53
69
  AGENT_ALIASES = {
54
70
  'Windows IE 6' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
71
+ 'Windows IE 7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
55
72
  'Windows Mozilla' => 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6',
56
73
  'Mac Safari' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.3',
57
74
  'Mac FireFox' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3',
58
75
  'Mac Mozilla' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401',
59
76
  'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624',
60
77
  'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)',
61
- 'Mechanize' => "WWW-Mechanize/#{Version} (http://rubyforge.org/projects/mechanize/)"
78
+ 'Mechanize' => "WWW-Mechanize/#{VERSION} (http://rubyforge.org/projects/mechanize/)"
62
79
  }
63
80
 
64
81
  attr_accessor :cookie_jar
@@ -219,9 +236,14 @@ class Mechanize
219
236
 
220
237
  # Returns whether or not a url has been visited
221
238
  def visited?(url)
239
+ ! visited_page(url).nil?
240
+ end
241
+
242
+ # Returns a visited page for the url passed in, otherwise nil
243
+ def visited_page(url)
222
244
  url = url.uri if url.respond_to? :uri
223
245
  uri = to_absolute_uri(url).to_s
224
- ! @history.find { |h| h.uri.to_s == uri }.nil?
246
+ @history.reverse.find { |h| h.uri.to_s == uri }
225
247
  end
226
248
 
227
249
  # Runs given block, then resets the page history as it was before. self is
@@ -262,6 +284,11 @@ class Mechanize
262
284
  # Add User-Agent header to request
263
285
  request.add_field('User-Agent', @user_agent) if @user_agent
264
286
 
287
+ # Add If-Modified-Since if page is in history
288
+ if( (page = visited_page(uri)) && page.response['Last-Modified'] )
289
+ request.add_field('If-Modified-Since', page.response['Last-Modified'])
290
+ end
291
+
265
292
  request.basic_auth(@user, @password) if @user || @password
266
293
  request
267
294
  end
@@ -269,14 +296,25 @@ class Mechanize
269
296
  private
270
297
 
271
298
  def to_absolute_uri(url, cur_page=current_page())
272
- url = URI.parse(
273
- URI.unescape(Util.html_unescape(url.to_s.strip)).gsub(/ /, '%20')
274
- ) unless url.is_a? URI
299
+ unless url.is_a? URI
300
+ url = url.to_s.strip
301
+ url = URI.parse(
302
+ Util.html_unescape(
303
+ url.split(/%[0-9A-Fa-f]{2}/).zip(
304
+ url.scan(/%[0-9A-Fa-f]{2}/)
305
+ ).map { |x,y|
306
+ "#{URI.escape(x)}#{y}"
307
+ }.join('')
308
+ ).gsub(/%23/, '#')
309
+ )
310
+ end
275
311
 
276
312
  # construct an absolute uri
277
313
  if url.relative?
278
314
  raise 'no history. please specify an absolute URL' unless cur_page.uri
279
315
  url = cur_page.uri + url
316
+ # Strip initial "/.." bits from the path
317
+ url.path.sub!(/^(\/\.\.)+(?=\/)/, '')
280
318
  end
281
319
 
282
320
  return url
@@ -403,21 +441,23 @@ class Mechanize
403
441
  response,
404
442
  response_body,
405
443
  response.code
406
- )
407
-
408
- page.mech = self if page.respond_to? :mech=
444
+ ) { |parser|
445
+ parser.mech = self if parser.respond_to? :mech=
446
+ if parser.respond_to?(:watch_for_set=) && @watch_for_set
447
+ parser.watch_for_set = @watch_for_set
448
+ end
449
+ }
409
450
 
410
451
  log.info("status: #{ page.code }") if log
411
452
 
412
- if page.respond_to? :watch_for_set
413
- page.watch_for_set = @watch_for_set
414
- end
415
-
416
453
  res_klass = Net::HTTPResponse::CODE_TO_OBJ[page.code.to_s]
417
454
 
418
455
  return page if res_klass <= Net::HTTPSuccess
419
456
 
420
- if res_klass <= Net::HTTPRedirection
457
+ if res_klass == Net::HTTPNotModified
458
+ log.debug("Got cached page") if log
459
+ return visited_page(uri)
460
+ elsif res_klass <= Net::HTTPRedirection
421
461
  return page unless follow_redirect?
422
462
  log.info("follow redirect to: #{ response['Location'] }") if log
423
463
  abs_uri = to_absolute_uri(response['Location'].to_s, page)
@@ -444,17 +484,31 @@ class Mechanize
444
484
 
445
485
  def add_to_history(page)
446
486
  @history.push(page)
447
- if @max_history and @history.size > @max_history
448
- # keep only the last @max_history entries
449
- @history = @history[@history.size - @max_history, @max_history]
487
+ if @max_history and @history.length > @max_history
488
+ while @history.length > @max_history
489
+ @history[0] = nil
490
+ @history.shift
491
+ end
450
492
  end
451
493
  end
452
494
 
495
+ # :stopdoc:
453
496
  class Util
454
497
  def self.html_unescape(s)
455
- s.to_s.gsub(/&amp;/, "&").gsub(/&quot;/, '"').gsub(/&gt;/, ">").gsub(/&lt;/, "<")
498
+ return s unless s
499
+ s.gsub(/&(\w+|#[0-9]+);/) { |match|
500
+ number = case match
501
+ when /&(\w+);/
502
+ Hpricot::NamedCharacters[$1]
503
+ when /&#([0-9]+);/
504
+ $1.to_i
505
+ end
506
+
507
+ number ? (number.chr rescue match) : match
508
+ }
456
509
  end
457
510
  end
511
+ # :startdoc:
458
512
  end
459
513
 
460
514
  end # module WWW
@@ -27,7 +27,11 @@ module WWW
27
27
  @response_code = page.code
28
28
  end
29
29
 
30
- def inspect; response_code; end
30
+ def to_s
31
+ "#{response_code} => #{Net::HTTPResponse::CODE_TO_OBJ[response_code]}"
32
+ end
33
+
34
+ def inspect; to_s; end
31
35
  end
32
36
  end
33
37
  end
@@ -26,6 +26,8 @@ module WWW
26
26
 
27
27
  attr_reader :fields, :buttons, :file_uploads, :radiobuttons, :checkboxes
28
28
  attr_reader :enctype
29
+
30
+ alias :elements :fields
29
31
 
30
32
  def initialize(form_node, elements_node)
31
33
  @form_node, @elements_node = form_node, elements_node
@@ -105,6 +107,11 @@ module WWW
105
107
  end
106
108
  end
107
109
 
110
+ # Removes all fields with name +field_name+.
111
+ def delete_field!(field_name)
112
+ @fields.delete_if{ |f| f.name == field_name}
113
+ end
114
+
108
115
  private
109
116
  def parse
110
117
  @fields = WWW::Mechanize::List.new
@@ -10,7 +10,12 @@ module WWW
10
10
  attr_accessor :name, :value
11
11
 
12
12
  def initialize(name, value)
13
- @name, @value = name, value
13
+ @name = Util.html_unescape(name)
14
+ @value = if value.is_a? String
15
+ Util.html_unescape(value)
16
+ else
17
+ value
18
+ end
14
19
  end
15
20
 
16
21
  def query_value
@@ -24,7 +29,6 @@ module WWW
24
29
  # of the file.
25
30
  # See the example in EXAMPLES[link://files/EXAMPLES_txt.html]
26
31
  class FileUpload < Field
27
- attr_accessor :name # Field name
28
32
  attr_accessor :file_name # File name
29
33
  attr_accessor :mime_type # Mime Type (Optional)
30
34
 
@@ -32,7 +36,7 @@ module WWW
32
36
  alias :file_data= :value=
33
37
 
34
38
  def initialize(name, file_name)
35
- @file_name = file_name
39
+ @file_name = Util.html_unescape(file_name)
36
40
  @file_data = nil
37
41
  super(name, @file_data)
38
42
  end
@@ -215,7 +219,7 @@ module WWW
215
219
  def initialize(node, select_list)
216
220
  node.attributes ||= {}
217
221
  @text = node.all_text
218
- @value = node.attributes['value']
222
+ @value = Util.html_unescape(node.attributes['value'])
219
223
  @selected = node.attributes.has_key?('selected') ? true : false
220
224
  @select_list = select_list # The select list this option belongs to
221
225
  end
@@ -1,3 +1,4 @@
1
+ # :enddoc:
1
2
  require 'hpricot'
2
3
  class Hpricot::Elem
3
4
  def all_text
@@ -1,4 +1,4 @@
1
- #
1
+ # :enddoc:
2
2
  # = net/http.rb
3
3
  #
4
4
  # Copyright (C) 1999-2005 Yukihiro Matsumoto
@@ -1,3 +1,4 @@
1
+ # :enddoc:
1
2
  =begin
2
3
 
3
4
  = $RCSfile: https.rb,v $ -- SSL/TLS enhancement for Net::HTTP.
@@ -1,4 +1,4 @@
1
- #
1
+ # :enddoc:
2
2
  # = net/protocol.rb
3
3
  #
4
4
  #--
@@ -18,45 +18,40 @@ module WWW
18
18
  class Page < File
19
19
  extend Forwardable
20
20
 
21
- attr_reader :root, :title, :watch_for_set
21
+ attr_reader :parser, :title, :watch_for_set
22
22
  attr_reader :frames, :iframes, :links, :forms, :meta, :watches
23
23
  attr_accessor :mech
24
24
 
25
+ alias :root :parser
26
+
25
27
  def initialize(uri=nil, response=nil, body=nil, code=nil, mech=nil)
26
28
  super(uri, response, body, code)
27
- @watch_for_set = {}
28
- @mech = mech
29
-
30
- yield self if block_given?
29
+ @watch_for_set ||= {}
30
+ @mech ||= mech
31
31
 
32
32
  raise Mechanize::ContentTypeError.new(response['content-type']) unless
33
33
  content_type() =~ /^text\/html/
34
34
 
35
35
  # construct parser and feed with HTML
36
36
  if body && response
37
- @root ||= Hpricot.parse(body)
37
+ @parser ||= Hpricot.parse(body)
38
38
  parse_html
39
39
  end
40
40
  end
41
41
 
42
- # Get the response header
43
- def header
44
- @response
45
- end
46
-
47
42
  # Get the content type
48
43
  def content_type
49
44
  @response['content-type']
50
45
  end
51
46
 
52
47
  # Search through the page like HPricot
53
- def_delegator :@root, :search, :search
54
- def_delegator :@root, :/, :/
55
- def_delegator :@root, :at, :at
48
+ def_delegator :@parser, :search, :search
49
+ def_delegator :@parser, :/, :/
50
+ def_delegator :@parser, :at, :at
56
51
 
57
52
  def watch_for_set=(obj)
58
53
  @watch_for_set = obj
59
- parse_html if @body
54
+ parse_html if @body && @watch_for_set
60
55
  end
61
56
 
62
57
  def form(name)
@@ -76,24 +71,24 @@ module WWW
76
71
  @watches = {}
77
72
 
78
73
  # Set the title
79
- @title = if (@root/'title').text.length > 0
80
- (@root/'title').text
74
+ @title = if (@parser/'title').text.length > 0
75
+ (@parser/'title').text
81
76
  end
82
77
 
83
78
  # Find all the form tags
84
- (@root/'form').each do |html_form|
79
+ (@parser/'form').each do |html_form|
85
80
  form = Form.new(html_form, @mech, self)
86
81
  form.action ||= @uri
87
82
  @forms << form
88
83
  end
89
84
 
90
85
  # Find all the 'a' tags
91
- (@root/'a').each do |node|
86
+ (@parser/'a').each do |node|
92
87
  @links << Link.new(node, @mech, self)
93
88
  end
94
89
 
95
90
  # Find all 'meta' tags
96
- (@root/'meta').each do |node|
91
+ (@parser/'meta').each do |node|
97
92
  next if node.attributes.nil?
98
93
  next unless node.attributes.has_key? 'http-equiv'
99
94
  next unless node.attributes.has_key? 'content'
@@ -108,19 +103,19 @@ module WWW
108
103
  end
109
104
 
110
105
  # Find all 'frame' tags
111
- (@root/'frame').each do |node|
106
+ (@parser/'frame').each do |node|
112
107
  @frames << Frame.new(node, @mech, self)
113
108
  end
114
109
 
115
110
  # Find all 'iframe' tags
116
- (@root/'iframe').each do |node|
111
+ (@parser/'iframe').each do |node|
117
112
  @iframes << Frame.new(node, @mech, self)
118
113
  end
119
114
 
120
115
  # Find all watch tags
121
116
  unless @watch_for_set.nil?
122
117
  @watch_for_set.each do |key, klass|
123
- (@root/key).each do |node|
118
+ (@parser/key).each do |node|
124
119
  @watches[key] ||= []
125
120
  @watches[key] << (klass ? klass.new(node) : node)
126
121
  end
@@ -18,11 +18,20 @@ module WWW
18
18
  #
19
19
  class File
20
20
  attr_accessor :uri, :response, :body, :code
21
+ alias :header :response
21
22
 
22
23
  alias :content :body
23
24
 
24
25
  def initialize(uri=nil, response=nil, body=nil, code=nil)
25
- @uri, @response, @body, @code = uri, response, body, code
26
+ @uri, @body, @code = uri, body, code
27
+ # Copy the headers in to a hash to prevent memory leaks
28
+ if response
29
+ @response = Headers.new
30
+ response.each { |k,v|
31
+ @response[k] = v
32
+ }
33
+ end
34
+ yield self if block_given?
26
35
  end
27
36
 
28
37
  # Use this method to save the content of this object to filename
@@ -50,7 +59,7 @@ module WWW
50
59
  attr_reader :filename
51
60
 
52
61
  def initialize(uri=nil, response=nil, body=nil, code=nil)
53
- @uri, @response, @body, @code = uri, response, body, code
62
+ super(uri, response, body, code)
54
63
  path = uri.path.empty? ? 'index.html' : uri.path.gsub(/^[\/]*/, '')
55
64
  path += 'index.html' if path =~ /\/$/
56
65
 
@@ -154,5 +163,14 @@ module WWW
154
163
  @parsers[content_type] = klass
155
164
  end
156
165
  end
166
+
167
+ class Headers < Hash
168
+ def [](key)
169
+ super(key.downcase)
170
+ end
171
+ def []=(key, value)
172
+ super(key.downcase, value)
173
+ end
174
+ end
157
175
  end
158
176
  end
@@ -1,4 +1,4 @@
1
- #
1
+ # :enddoc:
2
2
  # Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de).
3
3
  # Released under the same terms of license as Ruby.
4
4
  #
@@ -1,6 +1,7 @@
1
1
  <html>
2
2
  <body>
3
3
  <a href="../tc_relative_links.html">dot dot slash</a>
4
+ <a href="../../../../../tc_relative_links.html">too many dots</a>
4
5
  <FRAMESET cols="20%, 80%">
5
6
  <FRAMESET rows="100, 200, 200">
6
7
  <FRAME name="frame1" src="../tc_relative_links.html">
@@ -0,0 +1,48 @@
1
+ require 'webrick'
2
+ require 'webrick/https'
3
+ require 'servlets'
4
+ require 'logger'
5
+
6
+ base_dir = FileTest.exists?(Dir::pwd + '/test') ? Dir::pwd + '/test' : Dir::pwd
7
+
8
+ s = WEBrick::HTTPServer.new(
9
+ :Port => 2002,
10
+ :DocumentRoot => base_dir + "/htdocs",
11
+ :SSLEnable => true,
12
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
13
+ :SSLCertificate => OpenSSL::X509::Certificate.new(
14
+ File.read("data/server.crt")
15
+ ),
16
+ :SSLPrivateKey => OpenSSL::PKey::RSA.new(
17
+ File.read("data/server.pem")
18
+ ),
19
+ :Logger => Logger.new(nil),
20
+ :AccessLog => Logger.new(nil)
21
+ )
22
+ s.mount("/one_cookie", OneCookieTest)
23
+ s.mount("/one_cookie_no_space", OneCookieNoSpacesTest)
24
+ s.mount("/many_cookies", ManyCookiesTest)
25
+ s.mount("/many_cookies_as_string", ManyCookiesAsStringTest)
26
+ s.mount("/send_cookies", SendCookiesTest)
27
+ s.mount("/form_post", FormTest)
28
+ s.mount("/form post", FormTest)
29
+ s.mount("/response_code", ResponseCodeTest)
30
+ s.mount("/file_upload", FileUploadTest)
31
+ s.mount("/bad_content_type", BadContentTypeTest)
32
+ s.mount("/content_type_test", ContentTypeTest)
33
+
34
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(base_dir + '/data/htpasswd')
35
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
36
+ :UserDB => htpasswd,
37
+ :Realm => 'mechanize',
38
+ :Logger => Logger.new(nil),
39
+ :AccessLog => Logger.new(nil)
40
+ )
41
+ s.mount_proc('/htpasswd_auth') { |req, res|
42
+ auth.authenticate(req, res)
43
+ res.body = "You are authenticated"
44
+ }
45
+
46
+ trap("INT") { s.stop }
47
+
48
+ s.start
@@ -23,6 +23,14 @@ module Enumerable
23
23
  end
24
24
 
25
25
  class CookieClassTest < Test::Unit::TestCase
26
+ def silently
27
+ warn_level = $VERBOSE
28
+ $VERBOSE = false
29
+ res = yield
30
+ $VERBOSE = warn_level
31
+ res
32
+ end
33
+
26
34
  def test_parse_dates
27
35
  url = URI.parse('http://localhost/')
28
36
 
@@ -47,9 +55,11 @@ class CookieClassTest < Test::Unit::TestCase
47
55
 
48
56
  dates.each do |date|
49
57
  cookie = "PREF=1; expires=#{date}"
50
- WWW::Mechanize::Cookie.parse(url, cookie) { |cookie|
51
- assert_equal(true, cookie.expires < yesterday)
52
- }
58
+ silently do
59
+ WWW::Mechanize::Cookie.parse(url, cookie) { |cookie|
60
+ assert_equal(true, cookie.expires < yesterday)
61
+ }
62
+ end
53
63
  end
54
64
  end
55
65
 
@@ -76,11 +86,13 @@ class CookieClassTest < Test::Unit::TestCase
76
86
  "20/06/95 21:07",
77
87
  ]
78
88
 
79
- dates.each do |date|
80
- cookie = "PREF=1; expires=#{date}"
81
- WWW::Mechanize::Cookie.parse(url, cookie) { |cookie|
82
- assert_equal(true, cookie.expires > (Time.now - 86400))
83
- }
89
+ silently do
90
+ dates.each do |date|
91
+ cookie = "PREF=1; expires=#{date}"
92
+ WWW::Mechanize::Cookie.parse(url, cookie) { |cookie|
93
+ assert_equal(true, cookie.expires > (Time.now - 86400))
94
+ }
95
+ end
84
96
  end
85
97
  end
86
98
 
@@ -120,6 +132,43 @@ class CookieClassTest < Test::Unit::TestCase
120
132
  end
121
133
  end
122
134
 
135
+ def test_parse_valid_cookie_empty_value
136
+ url = URI.parse('http://rubyforge.org/')
137
+ cookie_params = {}
138
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
139
+ cookie_params['path'] = 'path=/'
140
+ cookie_params['domain'] = 'domain=.rubyforge.org'
141
+ cookie_params['httponly'] = 'HttpOnly'
142
+ cookie_value = '12345%7D='
143
+
144
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
145
+
146
+ cookie_params.keys.combine.each do |c|
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::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
157
+ assert_not_nil(cookie)
158
+ assert_equal('12345%7D=', cookie.to_s)
159
+ assert_equal('', cookie.value)
160
+ assert_equal('/', cookie.path)
161
+ assert_equal('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
+
123
172
  # If no path was given, use the one from the URL
124
173
  def test_cookie_using_url_path
125
174
  url = URI.parse('http://rubyforge.org/login')
@@ -43,6 +43,33 @@ class CookieJarTest < Test::Unit::TestCase
43
43
  assert_equal(2, jar.cookies(url2).length)
44
44
  end
45
45
 
46
+ def test_empty_value
47
+ values = { :name => 'Foo',
48
+ :value => '',
49
+ :path => '/',
50
+ :expires => Time.now + (10 * 86400),
51
+ :domain => 'rubyforge.org'
52
+ }
53
+ url = URI.parse('http://rubyforge.org/')
54
+
55
+ jar = WWW::Mechanize::CookieJar.new
56
+ assert_equal(0, jar.cookies(url).length)
57
+
58
+ # Add one cookie with an expiration date in the future
59
+ cookie = cookie_from_hash(values)
60
+ jar.add(url, cookie)
61
+ assert_equal(1, jar.cookies(url).length)
62
+
63
+ jar.add(url, cookie_from_hash( values.merge( :domain => 'RuByForge.Org',
64
+ :name => 'aaron'
65
+ ) ) )
66
+
67
+ assert_equal(2, jar.cookies(url).length)
68
+
69
+ url2 = URI.parse('http://RuByFoRgE.oRg/')
70
+ assert_equal(2, jar.cookies(url2).length)
71
+ end
72
+
46
73
  def test_add_future_cookies
47
74
  values = { :name => 'Foo',
48
75
  :value => 'Bar',
data/test/tc_forms.rb CHANGED
@@ -500,6 +500,18 @@ class FormsMechTest < Test::Unit::TestCase
500
500
  assert_not_nil(f)
501
501
  assert_equal(number_of_fields + 1, form.fields.length)
502
502
  end
503
+
504
+ def test_delete_field
505
+ page = @agent.get("http://localhost:#{PORT}/form_multival.html")
506
+ form = page.forms.name('post_form').first
507
+
508
+ assert_not_nil(form)
509
+ number_of_fields = form.fields.length
510
+
511
+ form.delete_field!('first')
512
+ assert_nil(form['first'])
513
+ assert_equal(number_of_fields - 2, form.fields.length)
514
+ end
503
515
 
504
516
  def test_has_field
505
517
  page = @agent.get("http://localhost:#{PORT}/form_multival.html")
@@ -0,0 +1,46 @@
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 TestCheckBoxes < Test::Unit::TestCase
9
+ include TestMethods
10
+
11
+ def test_field
12
+ f = WWW::Mechanize::Field.new('a&amp;b', 'a&amp;b')
13
+ assert_equal('a&b', f.name)
14
+ assert_equal('a&b', f.value)
15
+
16
+ f = WWW::Mechanize::Field.new('a&b', 'a&b')
17
+ assert_equal('a&b', f.name)
18
+ assert_equal('a&b', f.value)
19
+
20
+ f = WWW::Mechanize::Field.new('a&#38;b', 'a&#38;b')
21
+ assert_equal('a&b', f.name)
22
+ assert_equal('a&b', f.value)
23
+ end
24
+
25
+ def test_file_upload
26
+ f = WWW::Mechanize::FileUpload.new('a&amp;b', 'a&amp;b')
27
+ assert_equal('a&b', f.name)
28
+ assert_equal('a&b', f.file_name)
29
+
30
+ f = WWW::Mechanize::FileUpload.new('a&b', 'a&b')
31
+ assert_equal('a&b', f.name)
32
+ assert_equal('a&b', f.file_name)
33
+ end
34
+
35
+ def test_image_button
36
+ f = WWW::Mechanize::ImageButton.new('a&amp;b', 'a&amp;b')
37
+ assert_equal('a&b', f.name)
38
+ assert_equal('a&b', f.value)
39
+ end
40
+
41
+ def test_radio_button
42
+ f = WWW::Mechanize::RadioButton.new('a&amp;b', 'a&amp;b', nil, nil)
43
+ assert_equal('a&b', f.name)
44
+ assert_equal('a&b', f.value)
45
+ end
46
+ end
@@ -0,0 +1,25 @@
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 TestIfModifiedSince < Test::Unit::TestCase
9
+ def setup
10
+ @agent = WWW::Mechanize.new
11
+ end
12
+
13
+ def test_get_twice
14
+ assert_equal(0, @agent.history.length)
15
+ page = @agent.get('http://localhost/if_modified_since')
16
+ assert_match(/You did not send/, page.body)
17
+
18
+ assert_equal(1, @agent.history.length)
19
+ page2 = @agent.get('http://localhost/if_modified_since')
20
+
21
+ assert_equal(2, @agent.history.length)
22
+ assert_equal(page.object_id, page2.object_id)
23
+ assert_match(/You did not send/, page.body)
24
+ end
25
+ end
data/test/tc_mech.rb CHANGED
@@ -13,6 +13,10 @@ class TestMechMethods < Test::Unit::TestCase
13
13
  @agent = WWW::Mechanize.new
14
14
  end
15
15
 
16
+ def test_weird_url
17
+ @agent.get('http://localhost/?action=bing&bang=boom=1|a=|b=|c=')
18
+ end
19
+
16
20
  def test_history
17
21
  0.upto(25) do |i|
18
22
  assert_equal(i, @agent.history.size)
@@ -24,6 +28,8 @@ class TestMechMethods < Test::Unit::TestCase
24
28
  @agent.history.last.uri.to_s)
25
29
  assert_equal("http://localhost:#{PORT}/",
26
30
  @agent.history[-2].uri.to_s)
31
+ assert_equal("http://localhost:#{PORT}/",
32
+ @agent.history[-2].uri.to_s)
27
33
 
28
34
  assert_equal(true, @agent.visited?("http://localhost:#{PORT}/"))
29
35
  assert_equal(true, @agent.visited?("/form_test.html"))
@@ -32,6 +38,16 @@ class TestMechMethods < Test::Unit::TestCase
32
38
 
33
39
  end
34
40
 
41
+ def test_visited
42
+ @agent.get("http://localhost/content_type_test?ct=application/pdf")
43
+ assert_equal(true,
44
+ @agent.visited?("http://localhost/content_type_test?ct=application/pdf"))
45
+ assert_equal(false,
46
+ @agent.visited?("http://localhost/content_type_test"))
47
+ assert_equal(false,
48
+ @agent.visited?("http://localhost/content_type_test?ct=text/html"))
49
+ end
50
+
35
51
  def test_max_history
36
52
  @agent.max_history = 10
37
53
  0.upto(10) do |i|
@@ -45,6 +61,23 @@ class TestMechMethods < Test::Unit::TestCase
45
61
  end
46
62
  end
47
63
 
64
+ def test_max_history_order
65
+ @agent.max_history = 2
66
+ assert_equal(0, @agent.history.length)
67
+
68
+ @agent.get('http://localhost/form_test.html')
69
+ assert_equal(1, @agent.history.length)
70
+
71
+ @agent.get('http://localhost/empty_form.html')
72
+ assert_equal(2, @agent.history.length)
73
+
74
+ @agent.get('http://localhost/tc_checkboxes.html')
75
+ assert_equal(2, @agent.history.length)
76
+ assert_equal('http://localhost/empty_form.html', @agent.history[0].uri.to_s)
77
+ assert_equal('http://localhost/tc_checkboxes.html',
78
+ @agent.history[1].uri.to_s)
79
+ end
80
+
48
81
  def test_back_button
49
82
  0.upto(5) do |i|
50
83
  assert_equal(i, @agent.history.size)
@@ -18,6 +18,13 @@ class TestRelativeLinks < Test::Unit::TestCase
18
18
  assert_equal('http://localhost/tc_relative_links.html', @agent.current_page.uri.to_s)
19
19
  end
20
20
 
21
+ def test_too_many_dots
22
+ @page = @agent.get("http://localhost/relative/tc_relative_links.html")
23
+ page = @page.links.text('too many dots').click
24
+ assert_not_nil(page)
25
+ assert_equal('http://localhost/tc_relative_links.html', page.uri.to_s)
26
+ end
27
+
21
28
  def test_go_forward
22
29
  @page = @agent.get("http://localhost/tc_relative_links.html")
23
30
  @page = @page.links.first.click
data/test/test_all.rb CHANGED
@@ -13,6 +13,8 @@ require 'tc_form_button'
13
13
  require 'tc_form_no_inputname'
14
14
  require 'tc_forms'
15
15
  require 'tc_gzipping'
16
+ require 'tc_html_unscape_forms'
17
+ require 'tc_if_modified_since'
16
18
  require 'tc_links'
17
19
  require 'tc_mech'
18
20
  require 'tc_multi_select'
@@ -30,6 +30,7 @@ class Net::HTTP
30
30
  '/many_cookies' => ManyCookiesTest,
31
31
  '/many_cookies_as_string' => ManyCookiesAsStringTest,
32
32
  '/send_cookies' => SendCookiesTest,
33
+ '/if_modified_since' => ModifiedSinceServlet,
33
34
  }
34
35
 
35
36
  PAGE_CACHE = {}
@@ -16,6 +16,27 @@ class RefererServlet < WEBrick::HTTPServlet::AbstractServlet
16
16
  end
17
17
  end
18
18
 
19
+ class ModifiedSinceServlet < WEBrick::HTTPServlet::AbstractServlet
20
+ def do_GET(req, res)
21
+ s_time = 'Fri, 04 May 2001 00:00:38 GMT'
22
+
23
+ my_time = Time.parse(s_time)
24
+
25
+ if req['If-Modified-Since']
26
+ your_time = Time.parse(req['If-Modified-Since'])
27
+ if my_time > your_time
28
+ res.body = 'This page was updated since you requested'
29
+ else
30
+ res.status = 304
31
+ end
32
+ else
33
+ res.body = 'You did not send an If-Modified-Since header'
34
+ end
35
+
36
+ res['Last-Modified'] = s_time
37
+ end
38
+ end
39
+
19
40
  class GzipServlet < WEBrick::HTTPServlet::AbstractServlet
20
41
  def do_GET(req, res)
21
42
  if req['Accept-Encoding'] =~ /gzip/
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: mechanize
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.6.4
7
- date: 2006-12-20 00:00:00 -08:00
6
+ version: 0.6.5
7
+ date: 2007-02-26 00:00:00 -08:00
8
8
  summary: Mechanize provides automated web-browsing
9
9
  require_paths:
10
10
  - lib
@@ -54,7 +54,6 @@ files:
54
54
  - lib/mechanize/hpricot.rb
55
55
  - lib/mechanize/inspect.rb
56
56
  - lib/mechanize/list.rb
57
- - lib/mechanize/mech_version.rb
58
57
  - lib/mechanize/net-overrides/net/http.rb
59
58
  - lib/mechanize/net-overrides/net/https.rb
60
59
  - lib/mechanize/net-overrides/net/protocol.rb
@@ -64,10 +63,46 @@ files:
64
63
  - lib/mechanize/pluggable_parsers.rb
65
64
  - lib/mechanize/rexml.rb
66
65
  - setup.rb
67
- test_files:
68
- - test/test_all.rb
69
- - test/test_includes.rb
70
- - test/test_servlets.rb
66
+ - test/data/htpasswd
67
+ - test/data/server.crt
68
+ - test/data/server.csr
69
+ - test/data/server.key
70
+ - test/data/server.pem
71
+ - test/htdocs/alt_text.html
72
+ - test/htdocs/bad_form_test.html
73
+ - test/htdocs/button.jpg
74
+ - test/htdocs/empty_form.html
75
+ - test/htdocs/file_upload.html
76
+ - test/htdocs/find_link.html
77
+ - test/htdocs/form_multi_select.html
78
+ - test/htdocs/form_multival.html
79
+ - test/htdocs/form_no_action.html
80
+ - test/htdocs/form_no_input_name.html
81
+ - test/htdocs/form_select.html
82
+ - test/htdocs/form_select_all.html
83
+ - test/htdocs/form_select_none.html
84
+ - test/htdocs/form_select_noopts.html
85
+ - test/htdocs/form_set_fields.html
86
+ - test/htdocs/form_test.html
87
+ - test/htdocs/frame_test.html
88
+ - test/htdocs/google.html
89
+ - test/htdocs/iframe_test.html
90
+ - test/htdocs/index.html
91
+ - test/htdocs/link with space.html
92
+ - test/htdocs/no_title_test.html
93
+ - test/htdocs/relative/tc_relative_links.html
94
+ - test/htdocs/tc_bad_links.html
95
+ - test/htdocs/tc_checkboxes.html
96
+ - test/htdocs/tc_encoded_links.html
97
+ - test/htdocs/tc_form_action.html
98
+ - test/htdocs/tc_links.html
99
+ - test/htdocs/tc_no_attributes.html
100
+ - test/htdocs/tc_pretty_print.html
101
+ - test/htdocs/tc_radiobuttons.html
102
+ - test/htdocs/tc_referer.html
103
+ - test/htdocs/tc_relative_links.html
104
+ - test/htdocs/tc_textarea.html
105
+ - test/ssl_server.rb
71
106
  - test/tc_authenticate.rb
72
107
  - test/tc_bad_links.rb
73
108
  - test/tc_checkboxes.rb
@@ -83,6 +118,8 @@ test_files:
83
118
  - test/tc_forms.rb
84
119
  - test/tc_frames.rb
85
120
  - test/tc_gzipping.rb
121
+ - test/tc_html_unscape_forms.rb
122
+ - test/tc_if_modified_since.rb
86
123
  - test/tc_links.rb
87
124
  - test/tc_mech.rb
88
125
  - test/tc_multi_select.rb
@@ -107,45 +144,11 @@ test_files:
107
144
  - test/tc_textarea.rb
108
145
  - test/tc_upload.rb
109
146
  - test/tc_watches.rb
110
- - test/htdocs/alt_text.html
111
- - test/htdocs/bad_form_test.html
112
- - test/htdocs/empty_form.html
113
- - test/htdocs/file_upload.html
114
- - test/htdocs/find_link.html
115
- - test/htdocs/form_multi_select.html
116
- - test/htdocs/form_multival.html
117
- - test/htdocs/form_no_action.html
118
- - test/htdocs/form_no_input_name.html
119
- - test/htdocs/form_select.html
120
- - test/htdocs/form_select_all.html
121
- - test/htdocs/form_select_none.html
122
- - test/htdocs/form_select_noopts.html
123
- - test/htdocs/form_set_fields.html
124
- - test/htdocs/form_test.html
125
- - test/htdocs/frame_test.html
126
- - test/htdocs/google.html
127
- - test/htdocs/iframe_test.html
128
- - test/htdocs/index.html
129
- - test/htdocs/link with space.html
130
- - test/htdocs/no_title_test.html
131
- - test/htdocs/tc_bad_links.html
132
- - test/htdocs/tc_checkboxes.html
133
- - test/htdocs/tc_encoded_links.html
134
- - test/htdocs/tc_form_action.html
135
- - test/htdocs/tc_links.html
136
- - test/htdocs/tc_no_attributes.html
137
- - test/htdocs/tc_pretty_print.html
138
- - test/htdocs/tc_radiobuttons.html
139
- - test/htdocs/tc_referer.html
140
- - test/htdocs/tc_relative_links.html
141
- - test/htdocs/tc_textarea.html
142
- - test/htdocs/relative/tc_relative_links.html
143
- - test/htdocs/button.jpg
144
- - test/data/server.crt
145
- - test/data/server.csr
146
- - test/data/server.key
147
- - test/data/server.pem
148
- - test/data/htpasswd
147
+ - test/test_all.rb
148
+ - test/test_includes.rb
149
+ - test/test_servlets.rb
150
+ test_files:
151
+ - test/test_all.rb
149
152
  rdoc_options: []
150
153
  extra_rdoc_files: []
151
154
  executables: []
@@ -161,4 +164,14 @@ dependencies:
161
164
  - ">"
162
165
  - !ruby/object:Gem::Version
163
166
  version: 0.0.0
167
+ version:
168
+ - !ruby/object:Gem::Dependency
169
+ name: hoe
170
+ version_requirement:
171
+ version_requirements: !ruby/object:Gem::Version::Requirement
172
+ requirements:
173
+ -
174
+ - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: 1.2.0
164
177
  version:
@@ -1,5 +0,0 @@
1
- module WWW
2
- class Mechanize
3
- Version = '0.6.4'
4
- end
5
- end