aai10-mechanize 2.0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/.autotest +6 -0
  2. data/.gitignore +9 -0
  3. data/CHANGELOG.rdoc +652 -0
  4. data/EXAMPLES.rdoc +187 -0
  5. data/FAQ.rdoc +11 -0
  6. data/GUIDE.rdoc +163 -0
  7. data/LICENSE.rdoc +20 -0
  8. data/Manifest.txt +172 -0
  9. data/README.rdoc +63 -0
  10. data/Rakefile +36 -0
  11. data/aai10-mechanize.gemspec +20 -0
  12. data/examples/flickr_upload.rb +22 -0
  13. data/examples/mech-dump.rb +5 -0
  14. data/examples/proxy_req.rb +7 -0
  15. data/examples/rubyforge.rb +20 -0
  16. data/examples/spider.rb +21 -0
  17. data/lib/mechanize.rb +664 -0
  18. data/lib/mechanize/content_type_error.rb +14 -0
  19. data/lib/mechanize/cookie.rb +116 -0
  20. data/lib/mechanize/cookie_jar.rb +202 -0
  21. data/lib/mechanize/element_matcher.rb +35 -0
  22. data/lib/mechanize/file.rb +80 -0
  23. data/lib/mechanize/file_connection.rb +17 -0
  24. data/lib/mechanize/file_request.rb +26 -0
  25. data/lib/mechanize/file_response.rb +74 -0
  26. data/lib/mechanize/file_saver.rb +37 -0
  27. data/lib/mechanize/form.rb +478 -0
  28. data/lib/mechanize/form/button.rb +9 -0
  29. data/lib/mechanize/form/check_box.rb +11 -0
  30. data/lib/mechanize/form/field.rb +44 -0
  31. data/lib/mechanize/form/file_upload.rb +23 -0
  32. data/lib/mechanize/form/image_button.rb +20 -0
  33. data/lib/mechanize/form/multi_select_list.rb +83 -0
  34. data/lib/mechanize/form/option.rb +49 -0
  35. data/lib/mechanize/form/radio_button.rb +48 -0
  36. data/lib/mechanize/form/select_list.rb +40 -0
  37. data/lib/mechanize/headers.rb +25 -0
  38. data/lib/mechanize/history.rb +83 -0
  39. data/lib/mechanize/http.rb +3 -0
  40. data/lib/mechanize/http/agent.rb +738 -0
  41. data/lib/mechanize/inspect.rb +88 -0
  42. data/lib/mechanize/monkey_patch.rb +37 -0
  43. data/lib/mechanize/page.rb +408 -0
  44. data/lib/mechanize/page/base.rb +8 -0
  45. data/lib/mechanize/page/frame.rb +27 -0
  46. data/lib/mechanize/page/image.rb +30 -0
  47. data/lib/mechanize/page/label.rb +20 -0
  48. data/lib/mechanize/page/link.rb +82 -0
  49. data/lib/mechanize/page/meta_refresh.rb +56 -0
  50. data/lib/mechanize/pluggable_parsers.rb +101 -0
  51. data/lib/mechanize/redirect_limit_reached_error.rb +16 -0
  52. data/lib/mechanize/redirect_not_get_or_head_error.rb +19 -0
  53. data/lib/mechanize/response_code_error.rb +22 -0
  54. data/lib/mechanize/response_read_error.rb +27 -0
  55. data/lib/mechanize/robots_disallowed_error.rb +29 -0
  56. data/lib/mechanize/unsupported_scheme_error.rb +8 -0
  57. data/lib/mechanize/util.rb +113 -0
  58. data/test/data/htpasswd +1 -0
  59. data/test/data/server.crt +16 -0
  60. data/test/data/server.csr +12 -0
  61. data/test/data/server.key +15 -0
  62. data/test/data/server.pem +15 -0
  63. data/test/helper.rb +175 -0
  64. data/test/htdocs/alt_text.html +10 -0
  65. data/test/htdocs/bad_form_test.html +9 -0
  66. data/test/htdocs/button.jpg +0 -0
  67. data/test/htdocs/canonical_uri.html +9 -0
  68. data/test/htdocs/dir with spaces/foo.html +1 -0
  69. data/test/htdocs/empty_form.html +6 -0
  70. data/test/htdocs/file_upload.html +26 -0
  71. data/test/htdocs/find_link.html +41 -0
  72. data/test/htdocs/form_multi_select.html +16 -0
  73. data/test/htdocs/form_multival.html +37 -0
  74. data/test/htdocs/form_no_action.html +18 -0
  75. data/test/htdocs/form_no_input_name.html +16 -0
  76. data/test/htdocs/form_select.html +16 -0
  77. data/test/htdocs/form_select_all.html +16 -0
  78. data/test/htdocs/form_select_none.html +17 -0
  79. data/test/htdocs/form_select_noopts.html +10 -0
  80. data/test/htdocs/form_set_fields.html +14 -0
  81. data/test/htdocs/form_test.html +188 -0
  82. data/test/htdocs/frame_referer_test.html +10 -0
  83. data/test/htdocs/frame_test.html +30 -0
  84. data/test/htdocs/google.html +13 -0
  85. data/test/htdocs/iframe_test.html +16 -0
  86. data/test/htdocs/index.html +6 -0
  87. data/test/htdocs/link with space.html +5 -0
  88. data/test/htdocs/meta_cookie.html +11 -0
  89. data/test/htdocs/no_title_test.html +6 -0
  90. data/test/htdocs/nofollow.html +9 -0
  91. data/test/htdocs/noindex.html +9 -0
  92. data/test/htdocs/norobots.html +8 -0
  93. data/test/htdocs/rails_3_encoding_hack_form_test.html +27 -0
  94. data/test/htdocs/rel_nofollow.html +8 -0
  95. data/test/htdocs/relative/tc_relative_links.html +21 -0
  96. data/test/htdocs/robots.html +8 -0
  97. data/test/htdocs/robots.txt +2 -0
  98. data/test/htdocs/tc_bad_charset.html +9 -0
  99. data/test/htdocs/tc_bad_links.html +5 -0
  100. data/test/htdocs/tc_base_images.html +10 -0
  101. data/test/htdocs/tc_base_link.html +8 -0
  102. data/test/htdocs/tc_blank_form.html +11 -0
  103. data/test/htdocs/tc_charset.html +6 -0
  104. data/test/htdocs/tc_checkboxes.html +19 -0
  105. data/test/htdocs/tc_encoded_links.html +5 -0
  106. data/test/htdocs/tc_field_precedence.html +11 -0
  107. data/test/htdocs/tc_follow_meta.html +8 -0
  108. data/test/htdocs/tc_form_action.html +48 -0
  109. data/test/htdocs/tc_images.html +8 -0
  110. data/test/htdocs/tc_links.html +18 -0
  111. data/test/htdocs/tc_meta_in_body.html +9 -0
  112. data/test/htdocs/tc_no_attributes.html +16 -0
  113. data/test/htdocs/tc_pretty_print.html +17 -0
  114. data/test/htdocs/tc_radiobuttons.html +17 -0
  115. data/test/htdocs/tc_referer.html +16 -0
  116. data/test/htdocs/tc_relative_links.html +19 -0
  117. data/test/htdocs/tc_textarea.html +23 -0
  118. data/test/htdocs/test_bad_encoding.html +52 -0
  119. data/test/htdocs/test_click.html +11 -0
  120. data/test/htdocs/unusual______.html +5 -0
  121. data/test/servlets.rb +402 -0
  122. data/test/ssl_server.rb +48 -0
  123. data/test/test_cookies.rb +129 -0
  124. data/test/test_form_action.rb +52 -0
  125. data/test/test_form_as_hash.rb +59 -0
  126. data/test/test_form_button.rb +46 -0
  127. data/test/test_frames.rb +34 -0
  128. data/test/test_headers.rb +33 -0
  129. data/test/test_history.rb +118 -0
  130. data/test/test_history_added.rb +16 -0
  131. data/test/test_html_unscape_forms.rb +46 -0
  132. data/test/test_if_modified_since.rb +20 -0
  133. data/test/test_images.rb +19 -0
  134. data/test/test_mechanize.rb +852 -0
  135. data/test/test_mechanize_cookie.rb +345 -0
  136. data/test/test_mechanize_cookie_jar.rb +433 -0
  137. data/test/test_mechanize_file.rb +53 -0
  138. data/test/test_mechanize_file_request.rb +19 -0
  139. data/test/test_mechanize_file_response.rb +21 -0
  140. data/test/test_mechanize_form.rb +576 -0
  141. data/test/test_mechanize_form_check_box.rb +37 -0
  142. data/test/test_mechanize_form_encoding.rb +120 -0
  143. data/test/test_mechanize_form_field.rb +21 -0
  144. data/test/test_mechanize_form_image_button.rb +12 -0
  145. data/test/test_mechanize_form_textarea.rb +51 -0
  146. data/test/test_mechanize_http_agent.rb +697 -0
  147. data/test/test_mechanize_link.rb +84 -0
  148. data/test/test_mechanize_page_encoding.rb +147 -0
  149. data/test/test_mechanize_page_link.rb +382 -0
  150. data/test/test_mechanize_page_meta_refresh.rb +115 -0
  151. data/test/test_mechanize_redirect_not_get_or_head_error.rb +18 -0
  152. data/test/test_mechanize_subclass.rb +22 -0
  153. data/test/test_mechanize_util.rb +92 -0
  154. data/test/test_multi_select.rb +118 -0
  155. data/test/test_no_attributes.rb +13 -0
  156. data/test/test_option.rb +18 -0
  157. data/test/test_pluggable_parser.rb +136 -0
  158. data/test/test_post_form.rb +37 -0
  159. data/test/test_pretty_print.rb +22 -0
  160. data/test/test_radiobutton.rb +75 -0
  161. data/test/test_redirect_limit_reached.rb +39 -0
  162. data/test/test_redirect_ok.rb +25 -0
  163. data/test/test_referer.rb +81 -0
  164. data/test/test_relative_links.rb +40 -0
  165. data/test/test_request.rb +13 -0
  166. data/test/test_response_code.rb +53 -0
  167. data/test/test_robots.rb +72 -0
  168. data/test/test_save_file.rb +48 -0
  169. data/test/test_scheme.rb +48 -0
  170. data/test/test_select.rb +119 -0
  171. data/test/test_select_all.rb +15 -0
  172. data/test/test_select_none.rb +15 -0
  173. data/test/test_select_noopts.rb +18 -0
  174. data/test/test_set_fields.rb +44 -0
  175. data/test/test_ssl_server.rb +20 -0
  176. metadata +360 -0
@@ -0,0 +1,345 @@
1
+ require "helper"
2
+
3
+ module Enumerable
4
+ def combine
5
+ masks = inject([[], 1]){|(ar, m), e| [ar << m, m << 1 ] }[0]
6
+ all = masks.inject(0){ |al, m| al|m }
7
+
8
+ result = []
9
+ for i in 1..all do
10
+ tmp = []
11
+ each_with_index do |e, idx|
12
+ tmp << e unless (masks[idx] & i) == 0
13
+ end
14
+ result << tmp
15
+ end
16
+ result
17
+ end
18
+ end
19
+
20
+ class TestMechanizeCookie < MiniTest::Unit::TestCase
21
+ def silently
22
+ warn_level = $VERBOSE
23
+ $VERBOSE = false
24
+ res = yield
25
+ $VERBOSE = warn_level
26
+ res
27
+ end
28
+
29
+ def test_parse_dates
30
+ url = URI.parse('http://localhost/')
31
+
32
+ yesterday = Time.now - 86400
33
+
34
+ dates = [ "14 Apr 89 03:20:12",
35
+ "14 Apr 89 03:20 GMT",
36
+ "Fri, 17 Mar 89 4:01:33",
37
+ "Fri, 17 Mar 89 4:01 GMT",
38
+ "Mon Jan 16 16:12 PDT 1989",
39
+ "Mon Jan 16 16:12 +0130 1989",
40
+ "6 May 1992 16:41-JST (Wednesday)",
41
+ #"22-AUG-1993 10:59:12.82",
42
+ "22-AUG-1993 10:59pm",
43
+ "22-AUG-1993 12:59am",
44
+ "22-AUG-1993 12:59 PM",
45
+ #"Friday, August 04, 1995 3:54 PM",
46
+ #"06/21/95 04:24:34 PM",
47
+ #"20/06/95 21:07",
48
+ "95-06-08 19:32:48 EDT",
49
+ ]
50
+
51
+ dates.each do |date|
52
+ cookie = "PREF=1; expires=#{date}"
53
+ silently do
54
+ Mechanize::Cookie.parse(url, cookie) { |c|
55
+ assert c.expires, "Tried parsing: #{date}"
56
+ assert_equal(true, c.expires < yesterday)
57
+ }
58
+ end
59
+ end
60
+ end
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
+
73
+ def test_parse_weird_cookie
74
+ cookie = 'n/a, ASPSESSIONIDCSRRQDQR=FBLDGHPBNDJCPCGNCPAENELB; path=/'
75
+ url = URI.parse('http://www.searchinnovation.com/')
76
+ Mechanize::Cookie.parse(url, cookie) { |c|
77
+ assert_equal('ASPSESSIONIDCSRRQDQR', c.name)
78
+ assert_equal('FBLDGHPBNDJCPCGNCPAENELB', c.value)
79
+ }
80
+ end
81
+
82
+ def test_double_semicolon
83
+ double_semi = 'WSIDC=WEST;; domain=.williams-sonoma.com; path=/'
84
+ url = URI.parse('http://williams-sonoma.com/')
85
+ Mechanize::Cookie.parse(url, double_semi) { |cookie|
86
+ assert_equal('WSIDC', cookie.name)
87
+ assert_equal('WEST', cookie.value)
88
+ }
89
+ end
90
+
91
+ def test_parse_bad_version
92
+ bad_cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Version=1.2; Content-type=text/html; Domain=192.168.6.196; expires=Friday, 13-November-2026 23:01:46 GMT;'
93
+ url = URI.parse('http://localhost/')
94
+ Mechanize::Cookie.parse(url, bad_cookie) { |cookie|
95
+ assert_nil(cookie.version)
96
+ }
97
+ end
98
+
99
+ def test_parse_bad_max_age
100
+ bad_cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Max-Age=1.2; Content-type=text/html; Domain=192.168.6.196; expires=Friday, 13-November-2026 23:01:46 GMT;'
101
+ url = URI.parse('http://localhost/')
102
+ Mechanize::Cookie.parse(url, bad_cookie) { |cookie|
103
+ assert_nil(cookie.max_age)
104
+ }
105
+ end
106
+
107
+ def test_parse_date_fail
108
+ url = URI.parse('http://localhost/')
109
+
110
+ dates = [
111
+ "20/06/95 21:07",
112
+ ]
113
+
114
+ silently do
115
+ dates.each do |date|
116
+ cookie = "PREF=1; expires=#{date}"
117
+ Mechanize::Cookie.parse(url, cookie) { |c|
118
+ assert_equal(true, c.expires.nil?)
119
+ }
120
+ end
121
+ end
122
+ end
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
+
164
+ def test_parse_valid_cookie
165
+ url = URI.parse('http://rubyforge.org/')
166
+ cookie_params = {}
167
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
168
+ cookie_params['path'] = 'path=/'
169
+ cookie_params['domain'] = 'domain=.rubyforge.org'
170
+ cookie_params['httponly'] = 'HttpOnly'
171
+ cookie_value = '12345%7D=ASDFWEE345%3DASda'
172
+
173
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
174
+
175
+ cookie_params.keys.combine.each do |c|
176
+ cookie_text = "#{cookie_value}; "
177
+ c.each_with_index do |key, idx|
178
+ if idx == (c.length - 1)
179
+ cookie_text << "#{cookie_params[key]}"
180
+ else
181
+ cookie_text << "#{cookie_params[key]}; "
182
+ end
183
+ end
184
+ cookie = nil
185
+ Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
186
+
187
+ assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
188
+ assert_equal('/', cookie.path)
189
+
190
+ # if expires was set, make sure we parsed it
191
+ if c.find { |k| k == 'expires' }
192
+ assert_equal(expires, cookie.expires)
193
+ else
194
+ assert_nil(cookie.expires)
195
+ end
196
+ end
197
+ end
198
+
199
+ def test_parse_valid_cookie_empty_value
200
+ url = URI.parse('http://rubyforge.org/')
201
+ cookie_params = {}
202
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
203
+ cookie_params['path'] = 'path=/'
204
+ cookie_params['domain'] = 'domain=.rubyforge.org'
205
+ cookie_params['httponly'] = 'HttpOnly'
206
+ cookie_value = '12345%7D='
207
+
208
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
209
+
210
+ cookie_params.keys.combine.each do |c|
211
+ cookie_text = "#{cookie_value}; "
212
+ c.each_with_index do |key, idx|
213
+ if idx == (c.length - 1)
214
+ cookie_text << "#{cookie_params[key]}"
215
+ else
216
+ cookie_text << "#{cookie_params[key]}; "
217
+ end
218
+ end
219
+ cookie = nil
220
+ Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
221
+
222
+ assert_equal('12345%7D=', cookie.to_s)
223
+ assert_equal('', cookie.value)
224
+ assert_equal('/', cookie.path)
225
+
226
+ # if expires was set, make sure we parsed it
227
+ if c.find { |k| k == 'expires' }
228
+ assert_equal(expires, cookie.expires)
229
+ else
230
+ assert_nil(cookie.expires)
231
+ end
232
+ end
233
+ end
234
+
235
+ # If no path was given, use the one from the URL
236
+ def test_cookie_using_url_path
237
+ url = URI.parse('http://rubyforge.org/login.php')
238
+ cookie_params = {}
239
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
240
+ cookie_params['path'] = 'path=/'
241
+ cookie_params['domain'] = 'domain=.rubyforge.org'
242
+ cookie_params['httponly'] = 'HttpOnly'
243
+ cookie_value = '12345%7D=ASDFWEE345%3DASda'
244
+
245
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
246
+
247
+ cookie_params.keys.combine.each do |c|
248
+ next if c.find { |k| k == 'path' }
249
+ cookie_text = "#{cookie_value}; "
250
+ c.each_with_index do |key, idx|
251
+ if idx == (c.length - 1)
252
+ cookie_text << "#{cookie_params[key]}"
253
+ else
254
+ cookie_text << "#{cookie_params[key]}; "
255
+ end
256
+ end
257
+ cookie = nil
258
+ Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
259
+
260
+ assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
261
+ assert_equal('/', cookie.path)
262
+
263
+ # if expires was set, make sure we parsed it
264
+ if c.find { |k| k == 'expires' }
265
+ assert_equal(expires, cookie.expires)
266
+ else
267
+ assert_nil(cookie.expires)
268
+ end
269
+ end
270
+ end
271
+
272
+ # Test using secure cookies
273
+ def test_cookie_with_secure
274
+ url = URI.parse('http://rubyforge.org/')
275
+ cookie_params = {}
276
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
277
+ cookie_params['path'] = 'path=/'
278
+ cookie_params['domain'] = 'domain=.rubyforge.org'
279
+ cookie_params['secure'] = 'secure'
280
+ cookie_value = '12345%7D=ASDFWEE345%3DASda'
281
+
282
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
283
+
284
+ cookie_params.keys.combine.each do |c|
285
+ next unless c.find { |k| k == 'secure' }
286
+ cookie_text = "#{cookie_value}; "
287
+ c.each_with_index do |key, idx|
288
+ if idx == (c.length - 1)
289
+ cookie_text << "#{cookie_params[key]}"
290
+ else
291
+ cookie_text << "#{cookie_params[key]}; "
292
+ end
293
+ end
294
+ cookie = nil
295
+ Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
296
+
297
+ assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
298
+ assert_equal('/', cookie.path)
299
+ assert_equal(true, cookie.secure)
300
+
301
+ # if expires was set, make sure we parsed it
302
+ if c.find { |k| k == 'expires' }
303
+ assert_equal(expires, cookie.expires)
304
+ else
305
+ assert_nil(cookie.expires)
306
+ end
307
+ end
308
+ end
309
+
310
+ def test_parse_cookie_no_spaces
311
+ url = URI.parse('http://rubyforge.org/')
312
+ cookie_params = {}
313
+ cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT'
314
+ cookie_params['path'] = 'path=/'
315
+ cookie_params['domain'] = 'domain=.rubyforge.org'
316
+ cookie_params['httponly'] = 'HttpOnly'
317
+ cookie_value = '12345%7D=ASDFWEE345%3DASda'
318
+
319
+ expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT')
320
+
321
+ cookie_params.keys.combine.each do |c|
322
+ cookie_text = "#{cookie_value};"
323
+ c.each_with_index do |key, idx|
324
+ if idx == (c.length - 1)
325
+ cookie_text << "#{cookie_params[key]}"
326
+ else
327
+ cookie_text << "#{cookie_params[key]};"
328
+ end
329
+ end
330
+ cookie = nil
331
+ Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie }
332
+
333
+ assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s)
334
+ assert_equal('/', cookie.path)
335
+
336
+ # if expires was set, make sure we parsed it
337
+ if c.find { |k| k == 'expires' }
338
+ assert_equal(expires, cookie.expires)
339
+ else
340
+ assert_nil(cookie.expires)
341
+ end
342
+ end
343
+ end
344
+ end
345
+
@@ -0,0 +1,433 @@
1
+ require 'helper'
2
+ require 'tmpdir'
3
+
4
+ class TestMechanizeCookieJar < MiniTest::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_does_not_reject_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(1, @jar.cookies(url).length)
168
+ end
169
+
170
+ def test_cookie_without_leading_dot_matches_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(1, @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_with_leading_dot_match_parent_domains
188
+ url = URI.parse('http://rubyforge.org/')
189
+
190
+ @jar.add(url, cookie_from_hash(cookie_values(:domain => '.rubyforge.org')))
191
+
192
+ assert_equal(1, @jar.cookies(url).length)
193
+ end
194
+
195
+ def test_cookies_with_leading_dot_match_parent_domains_exactly
196
+ url = URI.parse('http://arubyforge.org/')
197
+
198
+ @jar.add(url, cookie_from_hash(cookie_values(:domain => '.rubyforge.org')))
199
+
200
+ assert_equal(0, @jar.cookies(url).length)
201
+ end
202
+
203
+ def test_cookies_dot
204
+ url = URI.parse('http://www.host.example/')
205
+
206
+ @jar.add(url,
207
+ cookie_from_hash(cookie_values(:domain => 'www.host.example')))
208
+
209
+ url = URI.parse('http://wwwxhost.example/')
210
+ assert_equal(0, @jar.cookies(url).length)
211
+ end
212
+
213
+ def test_clear_bang
214
+ url = URI.parse('http://rubyforge.org/')
215
+
216
+ # Add one cookie with an expiration date in the future
217
+ cookie = cookie_from_hash(cookie_values)
218
+ @jar.add(url, cookie)
219
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
220
+ assert_equal(2, @jar.cookies(url).length)
221
+
222
+ @jar.clear!
223
+
224
+ assert_equal(0, @jar.cookies(url).length)
225
+ end
226
+
227
+ def test_save_cookies_yaml
228
+ url = URI.parse('http://rubyforge.org/')
229
+
230
+ # Add one cookie with an expiration date in the future
231
+ cookie = cookie_from_hash(cookie_values)
232
+ s_cookie = cookie_from_hash(cookie_values(:name => 'Bar',
233
+ :expires => nil,
234
+ :session => true))
235
+
236
+ @jar.add(url, cookie)
237
+ @jar.add(url, s_cookie)
238
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
239
+
240
+ assert_equal(3, @jar.cookies(url).length)
241
+
242
+ @jar.save_as("cookies.yml")
243
+
244
+ jar = Mechanize::CookieJar.new
245
+ jar.load("cookies.yml")
246
+ assert_equal(2, jar.cookies(url).length)
247
+
248
+ assert_equal(3, @jar.cookies(url).length)
249
+ end
250
+
251
+ def test_save_cookies_cookiestxt
252
+ url = URI.parse('http://rubyforge.org/')
253
+
254
+ # Add one cookie with an expiration date in the future
255
+ cookie = cookie_from_hash(cookie_values)
256
+ s_cookie = cookie_from_hash(cookie_values(:name => 'Bar',
257
+ :expires => nil,
258
+ :session => true))
259
+
260
+ @jar.add(url, cookie)
261
+ @jar.add(url, s_cookie)
262
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
263
+
264
+ assert_equal(3, @jar.cookies(url).length)
265
+
266
+ @jar.save_as("cookies.txt", :cookiestxt)
267
+
268
+ jar = Mechanize::CookieJar.new
269
+ jar.load("cookies.txt", :cookiestxt) # HACK test the format
270
+ assert_equal(2, jar.cookies(url).length)
271
+
272
+ assert_equal(3, @jar.cookies(url).length)
273
+ end
274
+
275
+ def test_expire_cookies
276
+ url = URI.parse('http://rubyforge.org/')
277
+
278
+ # Add one cookie with an expiration date in the future
279
+ cookie = cookie_from_hash(cookie_values)
280
+ @jar.add(url, cookie)
281
+ assert_equal(1, @jar.cookies(url).length)
282
+
283
+ # Add a second cookie
284
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
285
+ assert_equal(2, @jar.cookies(url).length)
286
+
287
+ # Make sure we can get the cookie from different paths
288
+ assert_equal(2, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
289
+
290
+ # Expire the first cookie
291
+ @jar.add(url, cookie_from_hash(
292
+ cookie_values(:expires => Time.now - (10 * 86400))))
293
+ assert_equal(1, @jar.cookies(url).length)
294
+
295
+ # Expire the second cookie
296
+ @jar.add(url, cookie_from_hash(
297
+ cookie_values( :name => 'Baz', :expires => Time.now - (10 * 86400))))
298
+ assert_equal(0, @jar.cookies(url).length)
299
+ end
300
+
301
+ def test_session_cookies
302
+ values = cookie_values(:expires => nil)
303
+ url = URI.parse('http://rubyforge.org/')
304
+
305
+ # Add one cookie with an expiration date in the future
306
+ cookie = cookie_from_hash(values)
307
+ @jar.add(url, cookie)
308
+ assert_equal(1, @jar.cookies(url).length)
309
+
310
+ # Add a second cookie
311
+ @jar.add(url, cookie_from_hash(values.merge(:name => 'Baz')))
312
+ assert_equal(2, @jar.cookies(url).length)
313
+
314
+ # Make sure we can get the cookie from different paths
315
+ assert_equal(2, @jar.cookies(URI.parse('http://rubyforge.org/login')).length)
316
+
317
+ # Expire the first cookie
318
+ @jar.add(url, cookie_from_hash(values.merge(:expires => Time.now - (10 * 86400))))
319
+ assert_equal(1, @jar.cookies(url).length)
320
+
321
+ # Expire the second cookie
322
+ @jar.add(url, cookie_from_hash(
323
+ values.merge(:name => 'Baz', :expires => Time.now - (10 * 86400))))
324
+ assert_equal(0, @jar.cookies(url).length)
325
+
326
+ # When given a URI with a blank path, CookieJar#cookies should return
327
+ # cookies with the path '/':
328
+ url = URI.parse('http://rubyforge.org')
329
+ assert_equal '', url.path
330
+ assert_equal(0, @jar.cookies(url).length)
331
+ # Now add a cookie with the path set to '/':
332
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'has_root_path',
333
+ :path => '/')))
334
+ assert_equal(1, @jar.cookies(url).length)
335
+ end
336
+
337
+ def test_paths
338
+ values = cookie_values(:path => "/login", :expires => nil)
339
+ url = URI.parse('http://rubyforge.org/login')
340
+
341
+ # Add one cookie with an expiration date in the future
342
+ cookie = cookie_from_hash(values)
343
+ @jar.add(url, cookie)
344
+ assert_equal(1, @jar.cookies(url).length)
345
+
346
+ # Add a second cookie
347
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' )))
348
+ assert_equal(2, @jar.cookies(url).length)
349
+
350
+ # Make sure we don't get the cookie in a different path
351
+ assert_equal(0, @jar.cookies(URI.parse('http://rubyforge.org/hello')).length)
352
+ assert_equal(0, @jar.cookies(URI.parse('http://rubyforge.org/')).length)
353
+
354
+ # Expire the first cookie
355
+ @jar.add(url, cookie_from_hash(values.merge( :expires => Time.now - (10 * 86400))))
356
+ assert_equal(1, @jar.cookies(url).length)
357
+
358
+ # Expire the second cookie
359
+ @jar.add(url, cookie_from_hash(values.merge( :name => 'Baz',
360
+ :expires => Time.now - (10 * 86400))))
361
+ assert_equal(0, @jar.cookies(url).length)
362
+ end
363
+
364
+ def test_save_and_read_cookiestxt
365
+ url = URI.parse('http://rubyforge.org/')
366
+
367
+ # Add one cookie with an expiration date in the future
368
+ cookie = cookie_from_hash(cookie_values)
369
+ @jar.add(url, cookie)
370
+ @jar.add(url, cookie_from_hash(cookie_values(:name => 'Baz')))
371
+ assert_equal(2, @jar.cookies(url).length)
372
+
373
+ @jar.save_as("cookies.txt", :cookiestxt)
374
+ @jar.clear!
375
+
376
+ @jar.load("cookies.txt", :cookiestxt)
377
+ assert_equal(2, @jar.cookies(url).length)
378
+ end
379
+
380
+ def test_save_and_read_cookiestxt_with_session_cookies
381
+ url = URI.parse('http://rubyforge.org/')
382
+
383
+ @jar.add(url, cookie_from_hash(cookie_values(:expires => nil)))
384
+ @jar.save_as("cookies.txt", :cookiestxt)
385
+ @jar.clear!
386
+
387
+ @jar.load("cookies.txt", :cookiestxt)
388
+ assert_equal(1, @jar.cookies(url).length)
389
+ assert_nil @jar.cookies(url).first.expires
390
+ end
391
+
392
+ def test_save_and_read_expired_cookies
393
+ url = URI.parse('http://rubyforge.org/')
394
+
395
+ @jar.jar['rubyforge.org'] = {}
396
+
397
+
398
+ @jar.add url, cookie_from_hash(cookie_values)
399
+
400
+ # HACK no asertion
401
+ end
402
+
403
+ def test_ssl_cookies
404
+ # thanks to michal "ocher" ochman for reporting the bug responsible for this test.
405
+ values = cookie_values(:expires => nil)
406
+ values_ssl = values.merge(:name => 'Baz', :domain => "#{values[:domain]}:443")
407
+ url = URI.parse('https://rubyforge.org/login')
408
+
409
+ cookie = cookie_from_hash(values)
410
+ @jar.add(url, cookie)
411
+ assert_equal(1, @jar.cookies(url).length, "did not handle SSL cookie")
412
+
413
+ cookie = cookie_from_hash(values_ssl)
414
+ @jar.add(url, cookie)
415
+ assert_equal(2, @jar.cookies(url).length, "did not handle SSL cookie with :443")
416
+ end
417
+
418
+ def test_secure_cookie
419
+ nurl = URI.parse('http://rubyforge.org/login')
420
+ surl = URI.parse('https://rubyforge.org/login')
421
+
422
+ ncookie = cookie_from_hash(cookie_values(:name => 'Foo1'))
423
+ scookie = cookie_from_hash(cookie_values(:name => 'Foo2', :secure => true))
424
+
425
+ @jar.add(nurl, ncookie)
426
+ @jar.add(nurl, scookie)
427
+ @jar.add(surl, ncookie)
428
+ @jar.add(surl, scookie)
429
+
430
+ assert_equal('Foo1', @jar.cookies(nurl).map { |c| c.name }.sort.join(' ') )
431
+ assert_equal('Foo1 Foo2', @jar.cookies(surl).map { |c| c.name }.sort.join(' ') )
432
+ end
433
+ end