neocoin-mechanize 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/.autotest +6 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +638 -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/examples/flickr_upload.rb +22 -0
  12. data/examples/mech-dump.rb +5 -0
  13. data/examples/proxy_req.rb +7 -0
  14. data/examples/rubyforge.rb +20 -0
  15. data/examples/spider.rb +21 -0
  16. data/lib/mechanize.rb +662 -0
  17. data/lib/mechanize/content_type_error.rb +14 -0
  18. data/lib/mechanize/cookie.rb +85 -0
  19. data/lib/mechanize/cookie_jar.rb +241 -0
  20. data/lib/mechanize/element_matcher.rb +35 -0
  21. data/lib/mechanize/file.rb +80 -0
  22. data/lib/mechanize/file_connection.rb +17 -0
  23. data/lib/mechanize/file_request.rb +26 -0
  24. data/lib/mechanize/file_response.rb +74 -0
  25. data/lib/mechanize/file_saver.rb +37 -0
  26. data/lib/mechanize/form.rb +478 -0
  27. data/lib/mechanize/form/button.rb +9 -0
  28. data/lib/mechanize/form/check_box.rb +11 -0
  29. data/lib/mechanize/form/field.rb +44 -0
  30. data/lib/mechanize/form/file_upload.rb +23 -0
  31. data/lib/mechanize/form/image_button.rb +20 -0
  32. data/lib/mechanize/form/multi_select_list.rb +83 -0
  33. data/lib/mechanize/form/option.rb +49 -0
  34. data/lib/mechanize/form/radio_button.rb +48 -0
  35. data/lib/mechanize/form/select_list.rb +40 -0
  36. data/lib/mechanize/headers.rb +25 -0
  37. data/lib/mechanize/history.rb +83 -0
  38. data/lib/mechanize/http.rb +3 -0
  39. data/lib/mechanize/http/agent.rb +738 -0
  40. data/lib/mechanize/inspect.rb +88 -0
  41. data/lib/mechanize/monkey_patch.rb +37 -0
  42. data/lib/mechanize/page.rb +408 -0
  43. data/lib/mechanize/page/base.rb +8 -0
  44. data/lib/mechanize/page/frame.rb +27 -0
  45. data/lib/mechanize/page/image.rb +30 -0
  46. data/lib/mechanize/page/label.rb +20 -0
  47. data/lib/mechanize/page/link.rb +82 -0
  48. data/lib/mechanize/page/meta_refresh.rb +56 -0
  49. data/lib/mechanize/pluggable_parsers.rb +101 -0
  50. data/lib/mechanize/redirect_limit_reached_error.rb +16 -0
  51. data/lib/mechanize/redirect_not_get_or_head_error.rb +19 -0
  52. data/lib/mechanize/response_code_error.rb +22 -0
  53. data/lib/mechanize/response_read_error.rb +27 -0
  54. data/lib/mechanize/robots_disallowed_error.rb +29 -0
  55. data/lib/mechanize/unsupported_scheme_error.rb +8 -0
  56. data/lib/mechanize/util.rb +113 -0
  57. data/test/data/htpasswd +1 -0
  58. data/test/data/server.crt +16 -0
  59. data/test/data/server.csr +12 -0
  60. data/test/data/server.key +15 -0
  61. data/test/data/server.pem +15 -0
  62. data/test/helper.rb +175 -0
  63. data/test/htdocs/alt_text.html +10 -0
  64. data/test/htdocs/bad_form_test.html +9 -0
  65. data/test/htdocs/button.jpg +0 -0
  66. data/test/htdocs/canonical_uri.html +9 -0
  67. data/test/htdocs/dir with spaces/foo.html +1 -0
  68. data/test/htdocs/empty_form.html +6 -0
  69. data/test/htdocs/file_upload.html +26 -0
  70. data/test/htdocs/find_link.html +41 -0
  71. data/test/htdocs/form_multi_select.html +16 -0
  72. data/test/htdocs/form_multival.html +37 -0
  73. data/test/htdocs/form_no_action.html +18 -0
  74. data/test/htdocs/form_no_input_name.html +16 -0
  75. data/test/htdocs/form_select.html +16 -0
  76. data/test/htdocs/form_select_all.html +16 -0
  77. data/test/htdocs/form_select_none.html +17 -0
  78. data/test/htdocs/form_select_noopts.html +10 -0
  79. data/test/htdocs/form_set_fields.html +14 -0
  80. data/test/htdocs/form_test.html +188 -0
  81. data/test/htdocs/frame_referer_test.html +10 -0
  82. data/test/htdocs/frame_test.html +30 -0
  83. data/test/htdocs/google.html +13 -0
  84. data/test/htdocs/iframe_test.html +16 -0
  85. data/test/htdocs/index.html +6 -0
  86. data/test/htdocs/link with space.html +5 -0
  87. data/test/htdocs/meta_cookie.html +11 -0
  88. data/test/htdocs/no_title_test.html +6 -0
  89. data/test/htdocs/nofollow.html +9 -0
  90. data/test/htdocs/noindex.html +9 -0
  91. data/test/htdocs/norobots.html +8 -0
  92. data/test/htdocs/rails_3_encoding_hack_form_test.html +27 -0
  93. data/test/htdocs/rel_nofollow.html +8 -0
  94. data/test/htdocs/relative/tc_relative_links.html +21 -0
  95. data/test/htdocs/robots.html +8 -0
  96. data/test/htdocs/robots.txt +2 -0
  97. data/test/htdocs/tc_bad_charset.html +9 -0
  98. data/test/htdocs/tc_bad_links.html +5 -0
  99. data/test/htdocs/tc_base_images.html +10 -0
  100. data/test/htdocs/tc_base_link.html +8 -0
  101. data/test/htdocs/tc_blank_form.html +11 -0
  102. data/test/htdocs/tc_charset.html +6 -0
  103. data/test/htdocs/tc_checkboxes.html +19 -0
  104. data/test/htdocs/tc_encoded_links.html +5 -0
  105. data/test/htdocs/tc_field_precedence.html +11 -0
  106. data/test/htdocs/tc_follow_meta.html +8 -0
  107. data/test/htdocs/tc_form_action.html +48 -0
  108. data/test/htdocs/tc_images.html +8 -0
  109. data/test/htdocs/tc_links.html +18 -0
  110. data/test/htdocs/tc_meta_in_body.html +9 -0
  111. data/test/htdocs/tc_no_attributes.html +16 -0
  112. data/test/htdocs/tc_pretty_print.html +17 -0
  113. data/test/htdocs/tc_radiobuttons.html +17 -0
  114. data/test/htdocs/tc_referer.html +16 -0
  115. data/test/htdocs/tc_relative_links.html +19 -0
  116. data/test/htdocs/tc_textarea.html +23 -0
  117. data/test/htdocs/test_bad_encoding.html +52 -0
  118. data/test/htdocs/test_click.html +11 -0
  119. data/test/htdocs/unusual______.html +5 -0
  120. data/test/servlets.rb +402 -0
  121. data/test/ssl_server.rb +48 -0
  122. data/test/test_cookies.rb +129 -0
  123. data/test/test_form_action.rb +52 -0
  124. data/test/test_form_as_hash.rb +59 -0
  125. data/test/test_form_button.rb +46 -0
  126. data/test/test_frames.rb +34 -0
  127. data/test/test_headers.rb +33 -0
  128. data/test/test_history.rb +118 -0
  129. data/test/test_history_added.rb +16 -0
  130. data/test/test_html_unscape_forms.rb +46 -0
  131. data/test/test_if_modified_since.rb +20 -0
  132. data/test/test_images.rb +19 -0
  133. data/test/test_mechanize.rb +842 -0
  134. data/test/test_mechanize_cookie.rb +345 -0
  135. data/test/test_mechanize_cookie_jar.rb +401 -0
  136. data/test/test_mechanize_file.rb +53 -0
  137. data/test/test_mechanize_file_request.rb +19 -0
  138. data/test/test_mechanize_file_response.rb +21 -0
  139. data/test/test_mechanize_form.rb +576 -0
  140. data/test/test_mechanize_form_check_box.rb +37 -0
  141. data/test/test_mechanize_form_encoding.rb +120 -0
  142. data/test/test_mechanize_form_field.rb +21 -0
  143. data/test/test_mechanize_form_image_button.rb +12 -0
  144. data/test/test_mechanize_form_textarea.rb +51 -0
  145. data/test/test_mechanize_http_agent.rb +697 -0
  146. data/test/test_mechanize_link.rb +84 -0
  147. data/test/test_mechanize_page_encoding.rb +147 -0
  148. data/test/test_mechanize_page_link.rb +382 -0
  149. data/test/test_mechanize_page_meta_refresh.rb +115 -0
  150. data/test/test_mechanize_redirect_not_get_or_head_error.rb +18 -0
  151. data/test/test_mechanize_subclass.rb +22 -0
  152. data/test/test_mechanize_util.rb +92 -0
  153. data/test/test_multi_select.rb +118 -0
  154. data/test/test_no_attributes.rb +13 -0
  155. data/test/test_option.rb +18 -0
  156. data/test/test_pluggable_parser.rb +136 -0
  157. data/test/test_post_form.rb +37 -0
  158. data/test/test_pretty_print.rb +22 -0
  159. data/test/test_radiobutton.rb +75 -0
  160. data/test/test_redirect_limit_reached.rb +39 -0
  161. data/test/test_referer.rb +81 -0
  162. data/test/test_relative_links.rb +40 -0
  163. data/test/test_request.rb +13 -0
  164. data/test/test_response_code.rb +53 -0
  165. data/test/test_robots.rb +72 -0
  166. data/test/test_save_file.rb +48 -0
  167. data/test/test_scheme.rb +48 -0
  168. data/test/test_select.rb +119 -0
  169. data/test/test_select_all.rb +15 -0
  170. data/test/test_select_none.rb +15 -0
  171. data/test/test_select_noopts.rb +18 -0
  172. data/test/test_set_fields.rb +44 -0
  173. data/test/test_ssl_server.rb +20 -0
  174. metadata +354 -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,401 @@
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_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
+
382
+ @jar.add url, cookie_from_hash(cookie_values)
383
+
384
+ # HACK no asertion
385
+ end
386
+
387
+ def test_ssl_cookies
388
+ # thanks to michal "ocher" ochman for reporting the bug responsible for this test.
389
+ values = cookie_values(:expires => nil)
390
+ values_ssl = values.merge(:domain => "#{values[:domain]}:443")
391
+ url = URI.parse('https://rubyforge.org/login')
392
+
393
+ cookie = cookie_from_hash(values)
394
+ @jar.add(url, cookie)
395
+ assert_equal(1, @jar.cookies(url).length, "did not handle SSL cookie")
396
+
397
+ cookie = cookie_from_hash(values_ssl)
398
+ @jar.add(url, cookie)
399
+ assert_equal(2, @jar.cookies(url).length, "did not handle SSL cookie with :443")
400
+ end
401
+ end