mechanize 1.0.1.beta.20110107104205 → 2.0.pre.1

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.

Files changed (89) hide show
  1. data.tar.gz.sig +2 -0
  2. data/{lib/mechanize/chain/post_connect_hook.rb → .gemtest} +0 -0
  3. data/CHANGELOG.rdoc +51 -6
  4. data/EXAMPLES.rdoc +5 -3
  5. data/GUIDE.rdoc +72 -32
  6. data/LICENSE.rdoc +20 -340
  7. data/Manifest.txt +20 -27
  8. data/README.rdoc +12 -9
  9. data/Rakefile +5 -2
  10. data/examples/spider.rb +13 -2
  11. data/lib/mechanize.rb +545 -267
  12. data/lib/mechanize/content_type_error.rb +1 -1
  13. data/lib/mechanize/cookie.rb +72 -65
  14. data/lib/mechanize/cookie_jar.rb +197 -148
  15. data/lib/mechanize/element_matcher.rb +35 -0
  16. data/lib/mechanize/file.rb +3 -1
  17. data/lib/mechanize/file_connection.rb +17 -0
  18. data/lib/mechanize/file_request.rb +26 -0
  19. data/lib/mechanize/file_response.rb +61 -47
  20. data/lib/mechanize/form.rb +57 -58
  21. data/lib/mechanize/form/image_button.rb +2 -3
  22. data/lib/mechanize/form/multi_select_list.rb +71 -55
  23. data/lib/mechanize/form/select_list.rb +34 -62
  24. data/lib/mechanize/monkey_patch.rb +13 -11
  25. data/lib/mechanize/page.rb +277 -270
  26. data/lib/mechanize/page/image.rb +6 -2
  27. data/lib/mechanize/redirect_limit_reached_error.rb +1 -1
  28. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -1
  29. data/lib/mechanize/response_code_error.rb +3 -3
  30. data/lib/mechanize/unsupported_scheme_error.rb +1 -1
  31. data/lib/mechanize/uri_resolver.rb +82 -0
  32. data/lib/mechanize/util.rb +76 -60
  33. data/test/helper.rb +35 -5
  34. data/test/htdocs/dir with spaces/foo.html +1 -0
  35. data/test/htdocs/rails_3_encoding_hack_form_test.html +27 -0
  36. data/test/htdocs/tc_base_images.html +10 -0
  37. data/test/htdocs/tc_images.html +8 -0
  38. data/test/htdocs/test_click.html +11 -0
  39. data/test/servlets.rb +3 -2
  40. data/test/test_authenticate.rb +5 -5
  41. data/test/test_errors.rb +8 -8
  42. data/test/test_follow_meta.rb +4 -4
  43. data/test/test_form_as_hash.rb +4 -4
  44. data/test/test_forms.rb +3 -7
  45. data/test/test_hash_api.rb +2 -2
  46. data/test/test_headers.rb +1 -1
  47. data/test/test_images.rb +19 -0
  48. data/test/test_mech.rb +6 -6
  49. data/test/test_mechanize.rb +687 -0
  50. data/test/{test_cookie_class.rb → test_mechanize_cookie.rb} +52 -45
  51. data/test/test_mechanize_cookie_jar.rb +400 -0
  52. data/test/test_mechanize_file.rb +7 -1
  53. data/test/test_mechanize_file_request.rb +19 -0
  54. data/test/test_mechanize_file_response.rb +21 -0
  55. data/test/test_mechanize_form_image_button.rb +12 -0
  56. data/test/test_mechanize_page.rb +165 -0
  57. data/test/test_mechanize_uri_resolver.rb +29 -0
  58. data/test/{test_util.rb → test_mechanize_util.rb} +1 -1
  59. data/test/test_multi_select.rb +12 -0
  60. data/test/test_post_form.rb +7 -0
  61. data/test/test_redirect_verb_handling.rb +6 -6
  62. data/test/test_scheme.rb +0 -7
  63. data/test/test_verbs.rb +3 -3
  64. metadata +106 -72
  65. metadata.gz.sig +0 -0
  66. data/lib/mechanize/chain.rb +0 -36
  67. data/lib/mechanize/chain/auth_headers.rb +0 -78
  68. data/lib/mechanize/chain/body_decoding_handler.rb +0 -50
  69. data/lib/mechanize/chain/connection_resolver.rb +0 -28
  70. data/lib/mechanize/chain/custom_headers.rb +0 -21
  71. data/lib/mechanize/chain/handler.rb +0 -9
  72. data/lib/mechanize/chain/header_resolver.rb +0 -48
  73. data/lib/mechanize/chain/parameter_resolver.rb +0 -22
  74. data/lib/mechanize/chain/pre_connect_hook.rb +0 -20
  75. data/lib/mechanize/chain/request_resolver.rb +0 -31
  76. data/lib/mechanize/chain/response_body_parser.rb +0 -36
  77. data/lib/mechanize/chain/response_header_handler.rb +0 -34
  78. data/lib/mechanize/chain/response_reader.rb +0 -39
  79. data/lib/mechanize/chain/ssl_resolver.rb +0 -40
  80. data/lib/mechanize/chain/uri_resolver.rb +0 -75
  81. data/test/chain/test_argument_validator.rb +0 -14
  82. data/test/chain/test_auth_headers.rb +0 -25
  83. data/test/chain/test_custom_headers.rb +0 -18
  84. data/test/chain/test_header_resolver.rb +0 -27
  85. data/test/chain/test_parameter_resolver.rb +0 -35
  86. data/test/chain/test_request_resolver.rb +0 -29
  87. data/test/chain/test_response_reader.rb +0 -24
  88. data/test/test_cookie_jar.rb +0 -324
  89. data/test/test_page.rb +0 -124
@@ -17,7 +17,7 @@ module Enumerable
17
17
  end
18
18
  end
19
19
 
20
- class CookieClassTest < Test::Unit::TestCase
20
+ class TestMechanizeCookie < Test::Unit::TestCase
21
21
  def silently
22
22
  warn_level = $VERBOSE
23
23
  $VERBOSE = false
@@ -59,6 +59,17 @@ class CookieClassTest < Test::Unit::TestCase
59
59
  end
60
60
  end
61
61
 
62
+ def test_parse_empty
63
+ cookie_str = 'a=b; ; c=d'
64
+
65
+ uri = URI.parse 'http://example'
66
+
67
+ Mechanize::Cookie.parse uri, cookie_str do |cookie|
68
+ assert_equal 'a', cookie.name
69
+ assert_equal 'b', cookie.value
70
+ end
71
+ end
72
+
62
73
  def test_parse_weird_cookie
63
74
  cookie = 'n/a, ASPSESSIONIDCSRRQDQR=FBLDGHPBNDJCPCGNCPAENELB; path=/'
64
75
  url = URI.parse('http://www.searchinnovation.com/')
@@ -110,6 +121,46 @@ class CookieClassTest < Test::Unit::TestCase
110
121
  end
111
122
  end
112
123
 
124
+ def test_parse_domain_dot
125
+ url = URI.parse('http://host.example.com/')
126
+
127
+ cookie_str = 'a=b; domain=.example.com'
128
+
129
+ cookie = Mechanize::Cookie.parse(url, cookie_str).first
130
+
131
+ assert_equal '.example.com', cookie.domain
132
+ end
133
+
134
+ def test_parse_domain_no_dot
135
+ url = URI.parse('http://host.example.com/')
136
+
137
+ cookie_str = 'a=b; domain=example.com'
138
+
139
+ cookie = Mechanize::Cookie.parse(url, cookie_str).first
140
+
141
+ assert_equal '.example.com', cookie.domain
142
+ end
143
+
144
+ def test_parse_domain_none
145
+ url = URI.parse('http://example.com/')
146
+
147
+ cookie_str = 'a=b;'
148
+
149
+ cookie = Mechanize::Cookie.parse(url, cookie_str).first
150
+
151
+ assert_equal 'example.com', cookie.domain
152
+ end
153
+
154
+ def test_parse_expires_session
155
+ cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Max-Age=1.2; Content-type=text/html; Domain=192.168.6.196; expires=;'
156
+
157
+ url = URI.parse('http://localhost/')
158
+
159
+ cookie = Mechanize::Cookie.parse(url, cookie).first
160
+
161
+ assert cookie.session
162
+ end
163
+
113
164
  def test_parse_valid_cookie
114
165
  url = URI.parse('http://rubyforge.org/')
115
166
  cookie_params = {}
@@ -135,7 +186,6 @@ class CookieClassTest < Test::Unit::TestCase
135
186
  assert_not_nil(cookie)
136
187
  assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
137
188
  assert_equal('/', cookie.path)
138
- assert_equal('rubyforge.org', cookie.domain)
139
189
 
140
190
  # if expires was set, make sure we parsed it
141
191
  if c.find { |k| k == 'expires' }
@@ -172,7 +222,6 @@ class CookieClassTest < Test::Unit::TestCase
172
222
  assert_equal('12345%7D=', cookie.to_s)
173
223
  assert_equal('', cookie.value)
174
224
  assert_equal('/', cookie.path)
175
- assert_equal('rubyforge.org', cookie.domain)
176
225
 
177
226
  # if expires was set, make sure we parsed it
178
227
  if c.find { |k| k == 'expires' }
@@ -209,7 +258,6 @@ class CookieClassTest < Test::Unit::TestCase
209
258
  Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
210
259
  assert_not_nil(cookie)
211
260
  assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
212
- assert_equal('rubyforge.org', cookie.domain)
213
261
  assert_equal('/', cookie.path)
214
262
 
215
263
  # if expires was set, make sure we parsed it
@@ -247,7 +295,6 @@ class CookieClassTest < Test::Unit::TestCase
247
295
  Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
248
296
  assert_not_nil(cookie)
249
297
  assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
250
- assert_equal('rubyforge.org', cookie.domain)
251
298
  assert_equal('/', cookie.path)
252
299
  assert_equal(true, cookie.secure)
253
300
 
@@ -260,45 +307,6 @@ class CookieClassTest < Test::Unit::TestCase
260
307
  end
261
308
  end
262
309
 
263
- # If no domain was given, we must use the one from the URL
264
- def test_cookie_with_url_domain
265
- url = URI.parse('http://login.rubyforge.org/')
266
- cookie_params = {}
267
- cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
268
- cookie_params['path'] = 'path=/'
269
- cookie_params['domain'] = 'domain=.rubyforge.org'
270
- cookie_params['httponly'] = 'HttpOnly'
271
- cookie_value = '12345%7D=ASDFWEE345%3DASda'
272
-
273
- expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
274
-
275
- cookie_params.keys.combine.each do |c|
276
- next if c.find { |k| k == 'domain' }
277
- cookie_text = "#{cookie_value}; "
278
- c.each_with_index do |key, idx|
279
- if idx == (c.length - 1)
280
- cookie_text << "#{cookie_params[key]}"
281
- else
282
- cookie_text << "#{cookie_params[key]}; "
283
- end
284
- end
285
- cookie = nil
286
- Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
287
- assert_not_nil(cookie)
288
- assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
289
- assert_equal('/', cookie.path)
290
-
291
- assert_equal('login.rubyforge.org', cookie.domain)
292
-
293
- # if expires was set, make sure we parsed it
294
- if c.find { |k| k == 'expires' }
295
- assert_equal(expires, cookie.expires)
296
- else
297
- assert_nil(cookie.expires)
298
- end
299
- end
300
- end
301
-
302
310
  def test_parse_cookie_no_spaces
303
311
  url = URI.parse('http://rubyforge.org/')
304
312
  cookie_params = {}
@@ -324,7 +332,6 @@ class CookieClassTest < Test::Unit::TestCase
324
332
  assert_not_nil(cookie)
325
333
  assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
326
334
  assert_equal('/', cookie.path)
327
- assert_equal('rubyforge.org', cookie.domain)
328
335
 
329
336
  # if expires was set, make sure we parsed it
330
337
  if c.find { |k| k == 'expires' }
@@ -0,0 +1,400 @@
1
+ require 'helper'
2
+ require 'tmpdir'
3
+
4
+ class TestMechanizeCookieJar < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @jar = Mechanize::CookieJar.new
8
+ @tmpdir = Dir.mktmpdir
9
+
10
+ @orig_dir = Dir.pwd
11
+ Dir.chdir @tmpdir
12
+ end
13
+
14
+ def teardown
15
+ Dir.chdir @orig_dir
16
+ FileUtils.remove_entry_secure @tmpdir
17
+ end
18
+
19
+ def cookie_values(options = {})
20
+ {
21
+ :name => 'Foo',
22
+ :value => 'Bar',
23
+ :path => '/',
24
+ :expires => Time.now + (10 * 86400),
25
+ :domain => 'rubyforge.org'
26
+ }.merge(options)
27
+ end
28
+
29
+ def cookie_from_hash(hash)
30
+ c = Mechanize::Cookie.new(hash[:name], hash[:value])
31
+ hash.each { |k,v|
32
+ next if k == :name || k == :value
33
+ c.send("#{k}=", v)
34
+ }
35
+ c
36
+ end
37
+
38
+ def test_two_cookies_same_domain_and_name_different_paths
39
+ url = URI.parse('http://rubyforge.org/')
40
+
41
+ cookie = cookie_from_hash(cookie_values)
42
+ @jar.add(url, cookie)
43
+ @jar.add(url, cookie_from_hash(cookie_values(:path => '/onetwo')))
44
+
45
+ assert_equal(1, @jar.cookies(url).length)
46
+ assert_equal 2, @jar.cookies(URI.parse('http://rubyforge.org/onetwo')).length
47
+ end
48
+
49
+ def test_domain_case
50
+ url = URI.parse('http://rubyforge.org/')
51
+
52
+ # Add one cookie with an expiration date in the future
53
+ cookie = cookie_from_hash(cookie_values)
54
+ @jar.add(url, cookie)
55
+ assert_equal(1, @jar.cookies(url).length)
56
+
57
+ @jar.add(url, cookie_from_hash(
58
+ cookie_values(:domain => 'RuByForge.Org', :name => 'aaron')))
59
+
60
+ assert_equal(2, @jar.cookies(url).length)
61
+
62
+ url2 = URI.parse('http://RuByFoRgE.oRg/')
63
+ assert_equal(2, @jar.cookies(url2).length)
64
+ end
65
+
66
+ def test_empty_value
67
+ values = cookie_values(:value => "")
68
+ url = URI.parse('http://rubyforge.org/')
69
+
70
+ # Add one cookie with an expiration date in the future
71
+ cookie = cookie_from_hash(values)
72
+ @jar.add(url, cookie)
73
+ assert_equal(1, @jar.cookies(url).length)
74
+
75
+ @jar.add(url, cookie_from_hash( values.merge( :domain => 'RuByForge.Org',
76
+ :name => 'aaron'
77
+ ) ) )
78
+
79
+ assert_equal(2, @jar.cookies(url).length)
80
+
81
+ url2 = URI.parse('http://RuByFoRgE.oRg/')
82
+ assert_equal(2, @jar.cookies(url2).length)
83
+ end
84
+
85
+ def test_add_future_cookies
86
+ url = URI.parse('http://rubyforge.org/')
87
+
88
+ # Add one cookie with an expiration date in the future
89
+ cookie = cookie_from_hash(cookie_values)
90
+ @jar.add(url, cookie)
91
+ assert_equal(1, @jar.cookies(url).length)
92
+
93
+ # Add the same cookie, and we should still only have one
94
+ @jar.add(url, cookie_from_hash(cookie_values))
95
+ assert_equal(1, @jar.cookies(url).length)
96
+
97
+ # Make sure we can get the cookie from different paths
98
+ assert_equal(1, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
99
+
100
+ # Make sure we can't get the cookie from different domains
101
+ assert_equal(0, @jar.cookies(URI.parse('http://google.com/')).length)
102
+ end
103
+
104
+ def test_add_multiple_cookies
105
+ url = URI.parse('http://rubyforge.org/')
106
+
107
+ # Add one cookie with an expiration date in the future
108
+ cookie = cookie_from_hash(cookie_values)
109
+ @jar.add(url, cookie)
110
+ assert_equal(1, @jar.cookies(url).length)
111
+
112
+ # Add the same cookie, and we should still only have one
113
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
114
+ assert_equal(2, @jar.cookies(url).length)
115
+
116
+ # Make sure we can get the cookie from different paths
117
+ assert_equal(2, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
118
+
119
+ # Make sure we can't get the cookie from different domains
120
+ assert_equal(0, @jar.cookies(URI.parse('http://google.com/')).length)
121
+ end
122
+
123
+ def test_add_rejects_cookies_that_do_not_contain_an_embedded_dot
124
+ url = URI.parse('http://rubyforge.org/')
125
+
126
+ tld_cookie = cookie_from_hash(cookie_values(:domain => '.org'))
127
+ @jar.add(url, tld_cookie)
128
+ single_dot_cookie = cookie_from_hash(cookie_values(:domain => '.'))
129
+ @jar.add(url, single_dot_cookie)
130
+
131
+ assert_equal(0, @jar.cookies(url).length)
132
+ end
133
+
134
+ def test_add_makes_exception_for_local_tld
135
+ url = URI.parse('http://example.local')
136
+
137
+ tld_cookie = cookie_from_hash(cookie_values(:domain => '.local'))
138
+ @jar.add(url, tld_cookie)
139
+
140
+ assert_equal(1, @jar.cookies(url).length)
141
+ end
142
+
143
+ def test_add_makes_exception_for_localhost
144
+ url = URI.parse('http://localhost')
145
+
146
+ tld_cookie = cookie_from_hash(cookie_values(:domain => 'localhost'))
147
+ @jar.add(url, tld_cookie)
148
+
149
+ assert_equal(1, @jar.cookies(url).length)
150
+ end
151
+
152
+ def test_add_cookie_for_the_parent_domain
153
+ url = URI.parse('http://x.foo.com')
154
+
155
+ cookie = cookie_from_hash(cookie_values(:domain => '.foo.com'))
156
+ @jar.add(url, cookie)
157
+
158
+ assert_equal(1, @jar.cookies(url).length)
159
+ end
160
+
161
+ def test_add_rejects_cookies_from_a_nested_subdomain
162
+ url = URI.parse('http://y.x.foo.com')
163
+
164
+ cookie = cookie_from_hash(cookie_values(:domain => '.foo.com'))
165
+ @jar.add(url, cookie)
166
+
167
+ assert_equal(0, @jar.cookies(url).length)
168
+ end
169
+
170
+ def test_cookie_without_leading_dot_does_not_match_subdomains
171
+ url = URI.parse('http://admin.rubyforge.org/')
172
+
173
+ cookie = cookie_from_hash(cookie_values(:domain => 'rubyforge.org'))
174
+ @jar.add(url, cookie)
175
+
176
+ assert_equal(0, @jar.cookies(url).length)
177
+ end
178
+
179
+ def test_cookies_with_leading_dot_match_subdomains
180
+ url = URI.parse('http://admin.rubyforge.org/')
181
+
182
+ @jar.add(url, cookie_from_hash(cookie_values(:domain => '.rubyforge.org')))
183
+
184
+ assert_equal(1, @jar.cookies(url).length)
185
+ end
186
+
187
+ def test_cookies_dot
188
+ url = URI.parse('http://www.host.example/')
189
+
190
+ @jar.add(url,
191
+ cookie_from_hash(cookie_values(:domain => 'www.host.example')))
192
+
193
+ url = URI.parse('http://wwwxhost.example/')
194
+ assert_equal(0, @jar.cookies(url).length)
195
+ end
196
+
197
+ def test_clear_bang
198
+ url = URI.parse('http://rubyforge.org/')
199
+
200
+ # Add one cookie with an expiration date in the future
201
+ cookie = cookie_from_hash(cookie_values)
202
+ @jar.add(url, cookie)
203
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
204
+ assert_equal(2, @jar.cookies(url).length)
205
+
206
+ @jar.clear!
207
+
208
+ assert_equal(0, @jar.cookies(url).length)
209
+ end
210
+
211
+ def test_save_cookies_yaml
212
+ url = URI.parse('http://rubyforge.org/')
213
+
214
+ # Add one cookie with an expiration date in the future
215
+ cookie = cookie_from_hash(cookie_values)
216
+ s_cookie = cookie_from_hash(cookie_values(:name => 'Bar',
217
+ :expires => nil,
218
+ :session => true))
219
+
220
+ @jar.add(url, cookie)
221
+ @jar.add(url, s_cookie)
222
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
223
+
224
+ assert_equal(3, @jar.cookies(url).length)
225
+
226
+ @jar.save_as("cookies.yml")
227
+
228
+ jar = Mechanize::CookieJar.new
229
+ jar.load("cookies.yml")
230
+ assert_equal(2, jar.cookies(url).length)
231
+
232
+ assert_equal(3, @jar.cookies(url).length)
233
+ end
234
+
235
+ def test_save_cookies_cookiestxt
236
+ url = URI.parse('http://rubyforge.org/')
237
+
238
+ # Add one cookie with an expiration date in the future
239
+ cookie = cookie_from_hash(cookie_values)
240
+ s_cookie = cookie_from_hash(cookie_values(:name => 'Bar',
241
+ :expires => nil,
242
+ :session => true))
243
+
244
+ @jar.add(url, cookie)
245
+ @jar.add(url, s_cookie)
246
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
247
+
248
+ assert_equal(3, @jar.cookies(url).length)
249
+
250
+ @jar.save_as("cookies.txt", :cookiestxt)
251
+
252
+ jar = Mechanize::CookieJar.new
253
+ jar.load("cookies.txt", :cookiestxt) # HACK test the format
254
+ assert_equal(2, jar.cookies(url).length)
255
+
256
+ assert_equal(3, @jar.cookies(url).length)
257
+ end
258
+
259
+ def test_expire_cookies
260
+ url = URI.parse('http://rubyforge.org/')
261
+
262
+ # Add one cookie with an expiration date in the future
263
+ cookie = cookie_from_hash(cookie_values)
264
+ @jar.add(url, cookie)
265
+ assert_equal(1, @jar.cookies(url).length)
266
+
267
+ # Add a second cookie
268
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
269
+ assert_equal(2, @jar.cookies(url).length)
270
+
271
+ # Make sure we can get the cookie from different paths
272
+ assert_equal(2, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
273
+
274
+ # Expire the first cookie
275
+ @jar.add(url, cookie_from_hash(
276
+ cookie_values(:expires => Time.now - (10 * 86400))))
277
+ assert_equal(1, @jar.cookies(url).length)
278
+
279
+ # Expire the second cookie
280
+ @jar.add(url, cookie_from_hash(
281
+ cookie_values( :name => 'Baz', :expires => Time.now - (10 * 86400))))
282
+ assert_equal(0, @jar.cookies(url).length)
283
+ end
284
+
285
+ def test_session_cookies
286
+ values = cookie_values(:expires => nil)
287
+ url = URI.parse('http://rubyforge.org/')
288
+
289
+ # Add one cookie with an expiration date in the future
290
+ cookie = cookie_from_hash(values)
291
+ @jar.add(url, cookie)
292
+ assert_equal(1, @jar.cookies(url).length)
293
+
294
+ # Add a second cookie
295
+ @jar.add(url, cookie_from_hash(values.merge(:name => 'Baz')))
296
+ assert_equal(2, @jar.cookies(url).length)
297
+
298
+ # Make sure we can get the cookie from different paths
299
+ assert_equal(2, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
300
+
301
+ # Expire the first cookie
302
+ @jar.add(url, cookie_from_hash(values.merge(:expires => Time.now - (10 * 86400))))
303
+ assert_equal(1, @jar.cookies(url).length)
304
+
305
+ # Expire the second cookie
306
+ @jar.add(url, cookie_from_hash(
307
+ values.merge(:name => 'Baz', :expires => Time.now - (10 * 86400))))
308
+ assert_equal(0, @jar.cookies(url).length)
309
+
310
+ # When given a URI with a blank path, CookieJar#cookies should return
311
+ # cookies with the path '/':
312
+ url = URI.parse('http://rubyforge.org')
313
+ assert_equal '', url.path
314
+ assert_equal(0, @jar.cookies(url).length)
315
+ # Now add a cookie with the path set to '/':
316
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'has_root_path',
317
+ :path => '/')))
318
+ assert_equal(1, @jar.cookies(url).length)
319
+ end
320
+
321
+ def test_paths
322
+ values = cookie_values(:path => "/login", :expires => nil)
323
+ url = URI.parse('http://rubyforge.org/login')
324
+
325
+ # Add one cookie with an expiration date in the future
326
+ cookie = cookie_from_hash(values)
327
+ @jar.add(url, cookie)
328
+ assert_equal(1, @jar.cookies(url).length)
329
+
330
+ # Add a second cookie
331
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' )))
332
+ assert_equal(2, @jar.cookies(url).length)
333
+
334
+ # Make sure we don't get the cookie in a different path
335
+ assert_equal(0, @jar.cookies(URI.parse('http://rubyforge.org/hello')).length)
336
+ assert_equal(0, @jar.cookies(URI.parse('http://rubyforge.org/')).length)
337
+
338
+ # Expire the first cookie
339
+ @jar.add(url, cookie_from_hash(values.merge( :expires => Time.now - (10 * 86400))))
340
+ assert_equal(1, @jar.cookies(url).length)
341
+
342
+ # Expire the second cookie
343
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'Baz',
344
+ :expires => Time.now - (10 * 86400))))
345
+ assert_equal(0, @jar.cookies(url).length)
346
+ end
347
+
348
+ def test_save_and_read_cookiestxt
349
+ url = URI.parse('http://rubyforge.org/')
350
+
351
+ # Add one cookie with an expiration date in the future
352
+ cookie = cookie_from_hash(cookie_values)
353
+ @jar.add(url, cookie)
354
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
355
+ assert_equal(2, @jar.cookies(url).length)
356
+
357
+ @jar.save_as("cookies.txt", :cookiestxt)
358
+ @jar.clear!
359
+
360
+ @jar.load("cookies.txt", :cookiestxt)
361
+ assert_equal(2, @jar.cookies(url).length)
362
+ end
363
+
364
+ def test_save_and_read_cookiestxt_with_session_cookies
365
+ url = URI.parse('http://rubyforge.org/')
366
+
367
+ @jar.add(url, cookie_from_hash(cookie_values(:expires => nil)))
368
+ @jar.save_as("cookies.txt", :cookiestxt)
369
+ @jar.clear!
370
+
371
+ @jar.load("cookies.txt", :cookiestxt)
372
+ assert_equal(1, @jar.cookies(url).length)
373
+ assert_nil @jar.cookies(url).first.expires
374
+ end
375
+
376
+ def test_save_and_read_expired_cookies
377
+ url = URI.parse('http://rubyforge.org/')
378
+
379
+ @jar.jar['rubyforge.org'] = {}
380
+
381
+ assert_nothing_raised do
382
+ @jar.add(url, cookie_from_hash(cookie_values))
383
+ end
384
+ end
385
+
386
+ def test_ssl_cookies
387
+ # thanks to michal "ocher" ochman for reporting the bug responsible for this test.
388
+ values = cookie_values(:expires => nil)
389
+ values_ssl = values.merge(:domain => "#{values[:domain]}:443")
390
+ url = URI.parse('https://rubyforge.org/login')
391
+
392
+ cookie = cookie_from_hash(values)
393
+ @jar.add(url, cookie)
394
+ assert_equal(1, @jar.cookies(url).length, "did not handle SSL cookie")
395
+
396
+ cookie = cookie_from_hash(values_ssl)
397
+ @jar.add(url, cookie)
398
+ assert_equal(2, @jar.cookies(url).length, "did not handle SSL cookie with :443")
399
+ end
400
+ end