sinatra-contrib 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +135 -0
  3. data/Rakefile +75 -0
  4. data/ideas.md +29 -0
  5. data/lib/sinatra/capture.rb +42 -0
  6. data/lib/sinatra/config_file.rb +151 -0
  7. data/lib/sinatra/content_for.rb +111 -0
  8. data/lib/sinatra/contrib.rb +39 -0
  9. data/lib/sinatra/contrib/all.rb +2 -0
  10. data/lib/sinatra/contrib/setup.rb +53 -0
  11. data/lib/sinatra/contrib/version.rb +45 -0
  12. data/lib/sinatra/cookies.rb +331 -0
  13. data/lib/sinatra/decompile.rb +113 -0
  14. data/lib/sinatra/engine_tracking.rb +96 -0
  15. data/lib/sinatra/extension.rb +95 -0
  16. data/lib/sinatra/json.rb +134 -0
  17. data/lib/sinatra/link_header.rb +132 -0
  18. data/lib/sinatra/multi_route.rb +81 -0
  19. data/lib/sinatra/namespace.rb +282 -0
  20. data/lib/sinatra/reloader.rb +384 -0
  21. data/lib/sinatra/respond_with.rb +245 -0
  22. data/lib/sinatra/streaming.rb +267 -0
  23. data/lib/sinatra/test_helpers.rb +87 -0
  24. data/sinatra-contrib.gemspec +125 -0
  25. data/spec/capture_spec.rb +80 -0
  26. data/spec/config_file/key_value.yml +6 -0
  27. data/spec/config_file/missing_env.yml +4 -0
  28. data/spec/config_file/with_envs.yml +7 -0
  29. data/spec/config_file/with_nested_envs.yml +11 -0
  30. data/spec/config_file_spec.rb +44 -0
  31. data/spec/content_for/different_key.erb +1 -0
  32. data/spec/content_for/different_key.erubis +1 -0
  33. data/spec/content_for/different_key.haml +2 -0
  34. data/spec/content_for/different_key.slim +2 -0
  35. data/spec/content_for/layout.erb +1 -0
  36. data/spec/content_for/layout.erubis +1 -0
  37. data/spec/content_for/layout.haml +1 -0
  38. data/spec/content_for/layout.slim +1 -0
  39. data/spec/content_for/multiple_blocks.erb +4 -0
  40. data/spec/content_for/multiple_blocks.erubis +4 -0
  41. data/spec/content_for/multiple_blocks.haml +8 -0
  42. data/spec/content_for/multiple_blocks.slim +8 -0
  43. data/spec/content_for/multiple_yields.erb +3 -0
  44. data/spec/content_for/multiple_yields.erubis +3 -0
  45. data/spec/content_for/multiple_yields.haml +3 -0
  46. data/spec/content_for/multiple_yields.slim +3 -0
  47. data/spec/content_for/passes_values.erb +1 -0
  48. data/spec/content_for/passes_values.erubis +1 -0
  49. data/spec/content_for/passes_values.haml +1 -0
  50. data/spec/content_for/passes_values.slim +1 -0
  51. data/spec/content_for/same_key.erb +1 -0
  52. data/spec/content_for/same_key.erubis +1 -0
  53. data/spec/content_for/same_key.haml +2 -0
  54. data/spec/content_for/same_key.slim +2 -0
  55. data/spec/content_for/takes_values.erb +1 -0
  56. data/spec/content_for/takes_values.erubis +1 -0
  57. data/spec/content_for/takes_values.haml +3 -0
  58. data/spec/content_for/takes_values.slim +3 -0
  59. data/spec/content_for_spec.rb +201 -0
  60. data/spec/cookies_spec.rb +782 -0
  61. data/spec/decompile_spec.rb +44 -0
  62. data/spec/extension_spec.rb +33 -0
  63. data/spec/json_spec.rb +115 -0
  64. data/spec/link_header_spec.rb +100 -0
  65. data/spec/multi_route_spec.rb +45 -0
  66. data/spec/namespace/foo.erb +1 -0
  67. data/spec/namespace/nested/foo.erb +1 -0
  68. data/spec/namespace_spec.rb +623 -0
  69. data/spec/okjson.rb +581 -0
  70. data/spec/reloader/app.rb.erb +40 -0
  71. data/spec/reloader_spec.rb +441 -0
  72. data/spec/respond_with/bar.erb +1 -0
  73. data/spec/respond_with/bar.json.erb +1 -0
  74. data/spec/respond_with/foo.html.erb +1 -0
  75. data/spec/respond_with/not_html.sass +2 -0
  76. data/spec/respond_with_spec.rb +289 -0
  77. data/spec/spec_helper.rb +6 -0
  78. data/spec/streaming_spec.rb +436 -0
  79. metadata +256 -0
@@ -0,0 +1,3 @@
1
+ = yield_content :foo
2
+ = yield_content :foo
3
+ = yield_content :foo
@@ -0,0 +1,3 @@
1
+ = yield_content :foo
2
+ = yield_content :foo
3
+ = yield_content :foo
@@ -0,0 +1 @@
1
+ <%= yield_content :foo, 1, 2 %>
@@ -0,0 +1 @@
1
+ <%= yield_content :foo, 1, 2 %>
@@ -0,0 +1 @@
1
+ = yield_content :foo, 1, 2
@@ -0,0 +1 @@
1
+ == yield_content :foo, 1, 2
@@ -0,0 +1 @@
1
+ <% content_for :foo do %>foo<% end %>
@@ -0,0 +1 @@
1
+ <% content_for :foo do %>foo<% end %>
@@ -0,0 +1,2 @@
1
+ - content_for :foo do
2
+ foo
@@ -0,0 +1,2 @@
1
+ - content_for :foo do
2
+ | foo
@@ -0,0 +1 @@
1
+ <% content_for :foo do |a, b| %><i><%= a %></i> <%= b %><% end %>
@@ -0,0 +1 @@
1
+ <% content_for :foo do |a, b| %><i><%= a %></i> <%= b %><% end %>
@@ -0,0 +1,3 @@
1
+ - content_for :foo do |a, b|
2
+ %i= a
3
+ =b
@@ -0,0 +1,3 @@
1
+ - content_for :foo do |a, b|
2
+ i= a
3
+ = b
@@ -0,0 +1,201 @@
1
+ require 'backports'
2
+ require_relative 'spec_helper'
3
+
4
+ describe Sinatra::ContentFor do
5
+ subject do
6
+ Sinatra.new do
7
+ helpers Sinatra::ContentFor
8
+ set :views, File.expand_path("../content_for", __FILE__)
9
+ end.new!
10
+ end
11
+
12
+ Tilt.prefer Tilt::ERBTemplate
13
+
14
+ extend Forwardable
15
+ def_delegators :subject, :content_for, :yield_content
16
+ def render(engine, template)
17
+ subject.send(:render, engine, template, :layout => false).gsub(/\s/, '')
18
+ end
19
+
20
+ describe "without templates" do
21
+ it 'renders blocks declared with the same key you use when rendering' do
22
+ content_for(:foo) { "foo" }
23
+ yield_content(:foo).should == "foo"
24
+ end
25
+
26
+ it 'renders blocks more than once' do
27
+ content_for(:foo) { "foo" }
28
+ 3.times { yield_content(:foo).should == "foo" }
29
+ end
30
+
31
+ it 'does not render a block with a different key' do
32
+ content_for(:bar) { "bar" }
33
+ yield_content(:foo).should be_empty
34
+ end
35
+
36
+ it 'renders multiple blocks with the same key' do
37
+ content_for(:foo) { "foo" }
38
+ content_for(:foo) { "bar" }
39
+ content_for(:bar) { "WON'T RENDER ME" }
40
+ content_for(:foo) { "baz" }
41
+ yield_content(:foo).should == "foobarbaz"
42
+ end
43
+
44
+ it 'renders multiple blocks more than once' do
45
+ content_for(:foo) { "foo" }
46
+ content_for(:foo) { "bar" }
47
+ content_for(:bar) { "WON'T RENDER ME" }
48
+ content_for(:foo) { "baz" }
49
+ 3.times { yield_content(:foo).should == "foobarbaz" }
50
+ end
51
+
52
+ it 'passes values to the blocks' do
53
+ content_for(:foo) { |a| a.upcase }
54
+ yield_content(:foo, 'a').should == "A"
55
+ yield_content(:foo, 'b').should == "B"
56
+ end
57
+ end
58
+
59
+ # TODO: liquid radius markaby builder nokogiri
60
+ engines = %w[erb erubis haml slim]
61
+
62
+ engines.each do |inner|
63
+ describe inner.capitalize do
64
+ before :all do
65
+ begin
66
+ require inner
67
+ rescue LoadError => e
68
+ pending "Skipping: " << e.message
69
+ end
70
+ end
71
+
72
+ describe "with yield_content in Ruby" do
73
+ it 'renders blocks declared with the same key you use when rendering' do
74
+ render inner, :same_key
75
+ yield_content(:foo).strip.should == "foo"
76
+ end
77
+
78
+ it 'renders blocks more than once' do
79
+ render inner, :same_key
80
+ 3.times { yield_content(:foo).strip.should == "foo" }
81
+ end
82
+
83
+ it 'does not render a block with a different key' do
84
+ render inner, :different_key
85
+ yield_content(:foo).should be_empty
86
+ end
87
+
88
+ it 'renders multiple blocks with the same key' do
89
+ render inner, :multiple_blocks
90
+ yield_content(:foo).gsub(/\s/, '').should == "foobarbaz"
91
+ end
92
+
93
+ it 'renders multiple blocks more than once' do
94
+ render inner, :multiple_blocks
95
+ 3.times { yield_content(:foo).gsub(/\s/, '').should == "foobarbaz" }
96
+ end
97
+
98
+ it 'passes values to the blocks' do
99
+ render inner, :takes_values
100
+ yield_content(:foo, 1, 2).gsub(/\s/, '').should == "<i>1</i>2"
101
+ end
102
+ end
103
+
104
+ describe "with content_for in Ruby" do
105
+ it 'renders blocks declared with the same key you use when rendering' do
106
+ content_for(:foo) { "foo" }
107
+ render(inner, :layout).should == "foo"
108
+ end
109
+
110
+ it 'renders blocks more than once' do
111
+ content_for(:foo) { "foo" }
112
+ render(inner, :multiple_yields).should == "foofoofoo"
113
+ end
114
+
115
+ it 'does not render a block with a different key' do
116
+ content_for(:bar) { "foo" }
117
+ render(inner, :layout).should be_empty
118
+ end
119
+
120
+ it 'renders multiple blocks with the same key' do
121
+ content_for(:foo) { "foo" }
122
+ content_for(:foo) { "bar" }
123
+ content_for(:bar) { "WON'T RENDER ME" }
124
+ content_for(:foo) { "baz" }
125
+ render(inner, :layout).should == "foobarbaz"
126
+ end
127
+
128
+ it 'renders multiple blocks more than once' do
129
+ content_for(:foo) { "foo" }
130
+ content_for(:foo) { "bar" }
131
+ content_for(:bar) { "WON'T RENDER ME" }
132
+ content_for(:foo) { "baz" }
133
+ render(inner, :multiple_yields).should == "foobarbazfoobarbazfoobarbaz"
134
+ end
135
+
136
+ it 'passes values to the blocks' do
137
+ content_for(:foo) { |a,b| "<i>#{a}</i>#{b}" }
138
+ render(inner, :passes_values).should == "<i>1</i>2"
139
+ end
140
+ end
141
+
142
+ engines.each do |outer|
143
+ describe "with yield_content in #{outer.capitalize}" do
144
+ def body
145
+ last_response.body.gsub(/\s/, '')
146
+ end
147
+
148
+ before :all do
149
+ begin
150
+ require outer
151
+ rescue LoadError => e
152
+ pending "Skipping: " << e.message
153
+ end
154
+ end
155
+
156
+ before do
157
+ mock_app do
158
+ helpers Sinatra::ContentFor
159
+ set inner, :layout_engine => outer
160
+ set :views, File.expand_path("../content_for", __FILE__)
161
+ get('/:view') { render(inner, params[:view].to_sym) }
162
+ get('/:layout/:view') do
163
+ render inner, params[:view].to_sym, :layout => params[:layout].to_sym
164
+ end
165
+ end
166
+ end
167
+
168
+ it 'renders blocks declared with the same key you use when rendering' do
169
+ get('/same_key').should be_ok
170
+ body.should == "foo"
171
+ end
172
+
173
+ it 'renders blocks more than once' do
174
+ get('/multiple_yields/same_key').should be_ok
175
+ body.should == "foofoofoo"
176
+ end
177
+
178
+ it 'does not render a block with a different key' do
179
+ get('/different_key').should be_ok
180
+ body.should be_empty
181
+ end
182
+
183
+ it 'renders multiple blocks with the same key' do
184
+ get('/multiple_blocks').should be_ok
185
+ body.should == "foobarbaz"
186
+ end
187
+
188
+ it 'renders multiple blocks more than once' do
189
+ get('/multiple_yields/multiple_blocks').should be_ok
190
+ body.should == "foobarbazfoobarbazfoobarbaz"
191
+ end
192
+
193
+ it 'passes values to the blocks' do
194
+ get('/passes_values/takes_values').should be_ok
195
+ body.should == "<i>1</i>2"
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,782 @@
1
+ require 'backports'
2
+ require_relative 'spec_helper'
3
+
4
+ describe Sinatra::Cookies do
5
+ def cookie_route(*cookies, &block)
6
+ result = nil
7
+ set_cookie(cookies)
8
+ @cookie_app.get('/') do
9
+ result = instance_eval(&block)
10
+ "ok"
11
+ end
12
+ get '/'
13
+ last_response.should be_ok
14
+ body.should be == "ok"
15
+ result
16
+ end
17
+
18
+ def cookies(*set_cookies)
19
+ cookie_route(*set_cookies) { cookies }
20
+ end
21
+
22
+ before do
23
+ app = nil
24
+ mock_app do
25
+ helpers Sinatra::Cookies
26
+ app = self
27
+ end
28
+ @cookie_app = app
29
+ clear_cookies
30
+ end
31
+
32
+ describe :cookie_route do
33
+ it 'runs the block' do
34
+ ran = false
35
+ cookie_route { ran = true }
36
+ ran.should be_true
37
+ end
38
+
39
+ it 'returns the block result' do
40
+ cookie_route { 42 }.should be == 42
41
+ end
42
+ end
43
+
44
+ describe :== do
45
+ it 'is comparable to hashes' do
46
+ cookies.should be == {}
47
+ end
48
+
49
+ it 'is comparable to anything that responds to to_hash' do
50
+ other = Struct.new(:to_hash).new({})
51
+ cookies.should be == other
52
+ end
53
+ end
54
+
55
+ describe :[] do
56
+ it 'allows access to request cookies' do
57
+ cookies("foo=bar")["foo"].should be == "bar"
58
+ end
59
+
60
+ it 'takes symbols as keys' do
61
+ cookies("foo=bar")[:foo].should be == "bar"
62
+ end
63
+
64
+ it 'returns nil for missing keys' do
65
+ cookies("foo=bar")['bar'].should be_nil
66
+ end
67
+
68
+ it 'allows access to response cookies' do
69
+ cookie_route do
70
+ response.set_cookie 'foo', 'bar'
71
+ cookies['foo']
72
+ end.should be == 'bar'
73
+ end
74
+
75
+ it 'favors response cookies over request cookies' do
76
+ cookie_route('foo=bar') do
77
+ response.set_cookie 'foo', 'baz'
78
+ cookies['foo']
79
+ end.should be == 'baz'
80
+ end
81
+
82
+
83
+ it 'takes the last value for response cookies' do
84
+ cookie_route do
85
+ response.set_cookie 'foo', 'bar'
86
+ response.set_cookie 'foo', 'baz'
87
+ cookies['foo']
88
+ end.should be == 'baz'
89
+ end
90
+ end
91
+
92
+ describe :[]= do
93
+ it 'sets cookies to httponly' do
94
+ cookie_route do
95
+ cookies['foo'] = 'bar'
96
+ response['Set-Cookie'].lines.detect { |l| l.start_with? 'foo=' }
97
+ end.should include('HttpOnly')
98
+ end
99
+
100
+ it 'sets the domain' do
101
+ cookie_route do
102
+ cookies['foo'] = 'bar'
103
+ response['Set-Cookie'].lines.detect { |l| l.start_with? 'foo=' }
104
+ end.should include('domain=example.org')
105
+ end
106
+
107
+ it 'sets path to / by default' do
108
+ cookie_route do
109
+ cookies['foo'] = 'bar'
110
+ response['Set-Cookie'].lines.detect { |l| l.start_with? 'foo=' }
111
+ end.should include('path=/')
112
+ end
113
+
114
+ it 'sets path to the script_name if app is nested' do
115
+ cookie_route do
116
+ request.script_name = '/foo'
117
+ cookies['foo'] = 'bar'
118
+ response['Set-Cookie'].lines.detect { |l| l.start_with? 'foo=' }
119
+ end.should include('path=/foo')
120
+ end
121
+
122
+ it 'sets a cookie' do
123
+ cookie_route { cookies['foo'] = 'bar' }
124
+ cookie_jar['foo'].should be == 'bar'
125
+ end
126
+
127
+ it 'adds a value to the cookies hash' do
128
+ cookie_route do
129
+ cookies['foo'] = 'bar'
130
+ cookies['foo']
131
+ end.should be == 'bar'
132
+ end
133
+ end
134
+
135
+ describe :assoc do
136
+ it 'behaves like Hash#assoc' do
137
+ cookies('foo=bar').assoc('foo') == ['foo', 'bar']
138
+ end
139
+ end if Hash.method_defined? :assoc
140
+
141
+ describe :clear do
142
+ it 'removes request cookies from cookies hash' do
143
+ jar = cookies('foo=bar')
144
+ jar['foo'].should be == 'bar'
145
+ jar.clear
146
+ jar['foo'].should be_nil
147
+ end
148
+
149
+ it 'removes response cookies from cookies hash' do
150
+ cookie_route do
151
+ cookies['foo'] = 'bar'
152
+ cookies.clear
153
+ cookies['foo']
154
+ end.should be_nil
155
+ end
156
+
157
+ it 'expiers existing cookies' do
158
+ cookie_route("foo=bar") do
159
+ cookies.clear
160
+ response['Set-Cookie']
161
+ end.should include("foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT")
162
+ end
163
+ end
164
+
165
+ describe :compare_by_identity? do
166
+ it { cookies.should_not be_compare_by_identity }
167
+ end
168
+
169
+ describe :default do
170
+ it { cookies.default.should be_nil }
171
+ end
172
+
173
+ describe :default_proc do
174
+ it { cookies.default_proc.should be_nil }
175
+ end
176
+
177
+ describe :delete do
178
+ it 'removes request cookies from cookies hash' do
179
+ jar = cookies('foo=bar')
180
+ jar['foo'].should be == 'bar'
181
+ jar.delete 'foo'
182
+ jar['foo'].should be_nil
183
+ end
184
+
185
+ it 'removes response cookies from cookies hash' do
186
+ cookie_route do
187
+ cookies['foo'] = 'bar'
188
+ cookies.clear
189
+ cookies['foo']
190
+ end.should be_nil
191
+ end
192
+
193
+ it 'expiers existing cookies' do
194
+ cookie_route("foo=bar") do
195
+ cookies.delete 'foo'
196
+ response['Set-Cookie']
197
+ end.should include("foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT")
198
+ end
199
+
200
+ it 'does not touch other cookies' do
201
+ cookie_route("foo=bar", "bar=baz") do
202
+ cookies.delete 'foo'
203
+ cookies['bar']
204
+ end.should be == 'baz'
205
+ end
206
+
207
+ it 'returns the previous value for request cookies' do
208
+ cookie_route("foo=bar") do
209
+ cookies.delete "foo"
210
+ end.should be == "bar"
211
+ end
212
+
213
+ it 'returns the previous value for response cookies' do
214
+ cookie_route do
215
+ cookies['foo'] = 'bar'
216
+ cookies.delete "foo"
217
+ end.should be == "bar"
218
+ end
219
+
220
+ it 'returns nil for non-existing cookies' do
221
+ cookie_route { cookies.delete("foo") }.should be_nil
222
+ end
223
+ end
224
+
225
+ describe :delete_if do
226
+ it 'deletes cookies that match the block' do
227
+ cookie_route('foo=bar') do
228
+ cookies['bar'] = 'baz'
229
+ cookies['baz'] = 'foo'
230
+ cookies.delete_if { |*a| a.include? 'bar' }
231
+ cookies.values_at 'foo', 'bar', 'baz'
232
+ end.should be == [nil, nil, 'foo']
233
+ end
234
+ end
235
+
236
+ describe :each do
237
+ it 'loops through cookies' do
238
+ keys = []
239
+ foo = nil
240
+ bar = nil
241
+
242
+ cookie_route('foo=bar', 'bar=baz') do
243
+ cookies.each do |key, value|
244
+ foo = value if key == 'foo'
245
+ bar = value if key == 'bar'
246
+ keys << key
247
+ end
248
+ end
249
+
250
+ keys.sort.should be == ['bar', 'foo']
251
+ foo.should be == 'bar'
252
+ bar.should be == 'baz'
253
+ end
254
+
255
+ it 'favors response over request cookies' do
256
+ seen = false
257
+ cookie_route('foo=bar') do
258
+ cookies[:foo] = 'baz'
259
+ cookies.each do |key, value|
260
+ key.should == 'foo'
261
+ value.should == 'baz'
262
+ seen.should == false
263
+ seen = true
264
+ end
265
+ end
266
+ end
267
+
268
+ it 'does not loop through deleted cookies' do
269
+ cookie_route('foo=bar') do
270
+ cookies.delete :foo
271
+ cookies.each { fail }
272
+ end
273
+ end
274
+
275
+ it 'returns an enumerator' do
276
+ cookie_route('foo=bar') do
277
+ enum = cookies.each
278
+ enum.each { |key, value| key.should == 'foo' }
279
+ end
280
+ end
281
+ end
282
+
283
+ describe :each_key do
284
+ it 'loops through cookies' do
285
+ keys = []
286
+
287
+ cookie_route('foo=bar', 'bar=baz') do
288
+ cookies.each_key do |key|
289
+ keys << key
290
+ end
291
+ end
292
+
293
+ keys.sort.should be == ['bar', 'foo']
294
+ end
295
+
296
+ it 'only yields keys once' do
297
+ seen = false
298
+ cookie_route('foo=bar') do
299
+ cookies[:foo] = 'baz'
300
+ cookies.each_key do |key|
301
+ seen.should == false
302
+ seen = true
303
+ end
304
+ end
305
+ end
306
+
307
+ it 'does not loop through deleted cookies' do
308
+ cookie_route('foo=bar') do
309
+ cookies.delete :foo
310
+ cookies.each_key { fail }
311
+ end
312
+ end
313
+
314
+ it 'returns an enumerator' do
315
+ cookie_route('foo=bar') do
316
+ enum = cookies.each_key
317
+ enum.each { |key| key.should == 'foo' }
318
+ end
319
+ end
320
+ end
321
+
322
+ describe :each_pair do
323
+ it 'loops through cookies' do
324
+ keys = []
325
+ foo = nil
326
+ bar = nil
327
+
328
+ cookie_route('foo=bar', 'bar=baz') do
329
+ cookies.each_pair do |key, value|
330
+ foo = value if key == 'foo'
331
+ bar = value if key == 'bar'
332
+ keys << key
333
+ end
334
+ end
335
+
336
+ keys.sort.should be == ['bar', 'foo']
337
+ foo.should be == 'bar'
338
+ bar.should be == 'baz'
339
+ end
340
+
341
+ it 'favors response over request cookies' do
342
+ seen = false
343
+ cookie_route('foo=bar') do
344
+ cookies[:foo] = 'baz'
345
+ cookies.each_pair do |key, value|
346
+ key.should == 'foo'
347
+ value.should == 'baz'
348
+ seen.should == false
349
+ seen = true
350
+ end
351
+ end
352
+ end
353
+
354
+ it 'does not loop through deleted cookies' do
355
+ cookie_route('foo=bar') do
356
+ cookies.delete :foo
357
+ cookies.each_pair { fail }
358
+ end
359
+ end
360
+
361
+ it 'returns an enumerator' do
362
+ cookie_route('foo=bar') do
363
+ enum = cookies.each_pair
364
+ enum.each { |key, value| key.should == 'foo' }
365
+ end
366
+ end
367
+ end
368
+
369
+ describe :each_value do
370
+ it 'loops through cookies' do
371
+ values = []
372
+
373
+ cookie_route('foo=bar', 'bar=baz') do
374
+ cookies.each_value do |value|
375
+ values << value
376
+ end
377
+ end
378
+
379
+ values.sort.should be == ['bar', 'baz']
380
+ end
381
+
382
+ it 'favors response over request cookies' do
383
+ seen = false
384
+ cookie_route('foo=bar') do
385
+ cookies[:foo] = 'baz'
386
+ cookies.each_value do |value|
387
+ value.should == 'baz'
388
+ seen.should == false
389
+ seen = true
390
+ end
391
+ end
392
+ end
393
+
394
+ it 'does not loop through deleted cookies' do
395
+ cookie_route('foo=bar') do
396
+ cookies.delete :foo
397
+ cookies.each_value { fail }
398
+ end
399
+ end
400
+
401
+ it 'returns an enumerator' do
402
+ cookie_route('foo=bar') do
403
+ enum = cookies.each_value
404
+ enum.each { |value| value.should == 'bar' }
405
+ end
406
+ end
407
+ end
408
+
409
+ describe :empty? do
410
+ it 'returns true if there are no cookies' do
411
+ cookies.should be_empty
412
+ end
413
+
414
+ it 'returns false if there are request cookies' do
415
+ cookies('foo=bar').should_not be_empty
416
+ end
417
+
418
+ it 'returns false if there are response cookies' do
419
+ cookie_route do
420
+ cookies['foo'] = 'bar'
421
+ cookies.empty?
422
+ end.should be_false
423
+ end
424
+
425
+ it 'becomes true if response cookies are removed' do
426
+ cookie_route do
427
+ cookies['foo'] = 'bar'
428
+ cookies.delete :foo
429
+ cookies.empty?
430
+ end.should be_true
431
+ end
432
+
433
+ it 'becomes true if request cookies are removed' do
434
+ cookie_route('foo=bar') do
435
+ cookies.delete :foo
436
+ cookies.empty?
437
+ end.should be_true
438
+ end
439
+
440
+ it 'becomes true after clear' do
441
+ cookie_route('foo=bar', 'bar=baz') do
442
+ cookies['foo'] = 'bar'
443
+ cookies.clear
444
+ cookies.empty?
445
+ end.should be_true
446
+ end
447
+ end
448
+
449
+ describe :fetch do
450
+ it 'returns values from request cookies' do
451
+ cookies('foo=bar').fetch('foo').should be == 'bar'
452
+ end
453
+
454
+ it 'returns values from response cookies' do
455
+ cookie_route do
456
+ cookies['foo'] = 'bar'
457
+ cookies.fetch('foo')
458
+ end.should be == 'bar'
459
+ end
460
+
461
+ it 'favors response over request cookies' do
462
+ cookie_route('foo=baz') do
463
+ cookies['foo'] = 'bar'
464
+ cookies.fetch('foo')
465
+ end.should be == 'bar'
466
+ end
467
+
468
+ it 'raises an exception if key does not exist' do
469
+ error = RUBY_VERSION >= '1.9' ? KeyError : IndexError
470
+ expect { cookies.fetch('foo') }.to raise_exception(error)
471
+ end
472
+
473
+ it 'returns the block result if missing' do
474
+ cookies.fetch('foo') { 'bar' }.should be == 'bar'
475
+ end
476
+ end
477
+
478
+ describe :flatten do
479
+ it { cookies('foo=bar').flatten.should be == {'foo' => 'bar'}.flatten }
480
+ end if Hash.method_defined? :flatten
481
+
482
+ describe :has_key? do
483
+ it 'checks request cookies' do
484
+ cookies('foo=bar').should have_key('foo')
485
+ end
486
+
487
+ it 'checks response cookies' do
488
+ jar = cookies
489
+ jar['foo'] = 'bar'
490
+ jar.should have_key(:foo)
491
+ end
492
+
493
+ it 'does not use deleted cookies' do
494
+ jar = cookies('foo=bar')
495
+ jar.delete :foo
496
+ jar.should_not have_key('foo')
497
+ end
498
+ end
499
+
500
+ describe :has_value? do
501
+ it 'checks request cookies' do
502
+ cookies('foo=bar').should have_value('bar')
503
+ end
504
+
505
+ it 'checks response cookies' do
506
+ jar = cookies
507
+ jar[:foo] = 'bar'
508
+ jar.should have_value('bar')
509
+ end
510
+
511
+ it 'does not use deleted cookies' do
512
+ jar = cookies('foo=bar')
513
+ jar.delete :foo
514
+ jar.should_not have_value('bar')
515
+ end
516
+ end
517
+
518
+ describe :include? do
519
+ it 'checks request cookies' do
520
+ cookies('foo=bar').should include('foo')
521
+ end
522
+
523
+ it 'checks response cookies' do
524
+ jar = cookies
525
+ jar['foo'] = 'bar'
526
+ jar.should include(:foo)
527
+ end
528
+
529
+ it 'does not use deleted cookies' do
530
+ jar = cookies('foo=bar')
531
+ jar.delete :foo
532
+ jar.should_not include('foo')
533
+ end
534
+ end
535
+
536
+ describe :index do
537
+ it 'checks request cookies' do
538
+ cookies('foo=bar').index('bar').should be == 'foo'
539
+ end
540
+
541
+ it 'checks response cookies' do
542
+ jar = cookies
543
+ jar['foo'] = 'bar'
544
+ jar.index('bar').should be == 'foo'
545
+ end
546
+
547
+ it 'returns nil when missing' do
548
+ cookies('foo=bar').index('baz').should be_nil
549
+ end
550
+ end if RUBY_VERSION < '1.9'
551
+
552
+ describe :keep_if do
553
+ it 'removes entries' do
554
+ jar = cookies('foo=bar', 'bar=baz')
555
+ jar.keep_if { |*args| args == ['bar', 'baz'] }
556
+ jar.should be == {'bar' => 'baz'}
557
+ end
558
+ end
559
+
560
+ describe :key do
561
+ it 'checks request cookies' do
562
+ cookies('foo=bar').key('bar').should be == 'foo'
563
+ end
564
+
565
+ it 'checks response cookies' do
566
+ jar = cookies
567
+ jar['foo'] = 'bar'
568
+ jar.key('bar').should be == 'foo'
569
+ end
570
+
571
+ it 'returns nil when missing' do
572
+ cookies('foo=bar').key('baz').should be_nil
573
+ end
574
+ end
575
+
576
+ describe :key? do
577
+ it 'checks request cookies' do
578
+ cookies('foo=bar').key?('foo').should be_true
579
+ end
580
+
581
+ it 'checks response cookies' do
582
+ jar = cookies
583
+ jar['foo'] = 'bar'
584
+ jar.key?(:foo).should be_true
585
+ end
586
+
587
+ it 'does not use deleted cookies' do
588
+ jar = cookies('foo=bar')
589
+ jar.delete :foo
590
+ jar.key?('foo').should be_false
591
+ end
592
+ end
593
+
594
+ describe :keys do
595
+ it { cookies('foo=bar').keys.should == ['foo'] }
596
+ end
597
+
598
+ describe :length do
599
+ it { cookies.length.should == 0 }
600
+ it { cookies('foo=bar').length.should == 1 }
601
+ end
602
+
603
+ describe :member? do
604
+ it 'checks request cookies' do
605
+ cookies('foo=bar').member?('foo').should be_true
606
+ end
607
+
608
+ it 'checks response cookies' do
609
+ jar = cookies
610
+ jar['foo'] = 'bar'
611
+ jar.member?(:foo).should be_true
612
+ end
613
+
614
+ it 'does not use deleted cookies' do
615
+ jar = cookies('foo=bar')
616
+ jar.delete :foo
617
+ jar.member?('foo').should be_false
618
+ end
619
+ end
620
+
621
+ describe :merge do
622
+ it 'is mergable with a hash' do
623
+ cookies('foo=bar').merge(:bar => :baz).should be == {"foo" => "bar", :bar => :baz}
624
+ end
625
+
626
+ it 'does not create cookies' do
627
+ jar = cookies('foo=bar')
628
+ jar.merge(:bar => 'baz')
629
+ jar.should_not include(:bar)
630
+ end
631
+
632
+ it 'takes a block for conflict resolution' do
633
+ update = {'foo' => 'baz', 'bar' => 'baz'}
634
+ merged = cookies('foo=bar').merge(update) do |key, old, other|
635
+ key.should be == 'foo'
636
+ old.should be == 'bar'
637
+ other.should be == 'baz'
638
+ 'foo'
639
+ end
640
+ merged['foo'].should be == 'foo'
641
+ end
642
+ end
643
+
644
+ describe :merge! do
645
+ it 'creates cookies' do
646
+ jar = cookies('foo=bar')
647
+ jar.merge! :bar => 'baz'
648
+ jar.should include('bar')
649
+ end
650
+
651
+ it 'overrides existing values' do
652
+ jar = cookies('foo=bar')
653
+ jar.merge! :foo => "baz"
654
+ jar["foo"].should be == "baz"
655
+ end
656
+
657
+ it 'takes a block for conflict resolution' do
658
+ update = {'foo' => 'baz', 'bar' => 'baz'}
659
+ jar = cookies('foo=bar')
660
+ jar.merge!(update) do |key, old, other|
661
+ key.should be == 'foo'
662
+ old.should be == 'bar'
663
+ other.should be == 'baz'
664
+ 'foo'
665
+ end
666
+ jar['foo'].should be == 'foo'
667
+ end
668
+ end
669
+
670
+ describe :rassoc do
671
+ it 'behaves like Hash#assoc' do
672
+ cookies('foo=bar').rassoc('bar') == ['foo', 'bar']
673
+ end
674
+ end if Hash.method_defined? :rassoc
675
+
676
+ describe :reject do
677
+ it 'removes entries from new hash' do
678
+ jar = cookies('foo=bar', 'bar=baz')
679
+ sub = jar.reject { |*args| args == ['bar', 'baz'] }
680
+ sub.should be == {'foo' => 'bar'}
681
+ jar['bar'].should be == 'baz'
682
+ end
683
+ end
684
+
685
+ describe :reject! do
686
+ it 'removes entries' do
687
+ jar = cookies('foo=bar', 'bar=baz')
688
+ jar.reject! { |*args| args == ['bar', 'baz'] }
689
+ jar.should be == {'foo' => 'bar'}
690
+ end
691
+ end
692
+
693
+ describe :replace do
694
+ it 'replaces entries' do
695
+ jar = cookies('foo=bar', 'bar=baz')
696
+ jar.replace 'foo' => 'baz', 'baz' => 'bar'
697
+ jar.should be == {'foo' => 'baz', 'baz' => 'bar'}
698
+ end
699
+ end
700
+
701
+ describe :select do
702
+ it 'removes entries from new hash' do
703
+ jar = cookies('foo=bar', 'bar=baz')
704
+ sub = jar.select { |*args| args != ['bar', 'baz'] }
705
+ sub.should be == {'foo' => 'bar'}.select { true }
706
+ jar['bar'].should be == 'baz'
707
+ end
708
+ end
709
+
710
+ describe :select! do
711
+ it 'removes entries' do
712
+ jar = cookies('foo=bar', 'bar=baz')
713
+ jar.select! { |*args| args != ['bar', 'baz'] }
714
+ jar.should be == {'foo' => 'bar'}
715
+ end
716
+ end if Hash.method_defined? :select!
717
+
718
+ describe :shift do
719
+ it 'removes from the hash' do
720
+ jar = cookies('foo=bar')
721
+ jar.shift.should be == ['foo', 'bar']
722
+ jar.should_not include('bar')
723
+ end
724
+ end
725
+
726
+ describe :size do
727
+ it { cookies.size.should == 0 }
728
+ it { cookies('foo=bar').size.should == 1 }
729
+ end
730
+
731
+ describe :update do
732
+ it 'creates cookies' do
733
+ jar = cookies('foo=bar')
734
+ jar.update :bar => 'baz'
735
+ jar.should include('bar')
736
+ end
737
+
738
+ it 'overrides existing values' do
739
+ jar = cookies('foo=bar')
740
+ jar.update :foo => "baz"
741
+ jar["foo"].should be == "baz"
742
+ end
743
+
744
+ it 'takes a block for conflict resolution' do
745
+ merge = {'foo' => 'baz', 'bar' => 'baz'}
746
+ jar = cookies('foo=bar')
747
+ jar.update(merge) do |key, old, other|
748
+ key.should be == 'foo'
749
+ old.should be == 'bar'
750
+ other.should be == 'baz'
751
+ 'foo'
752
+ end
753
+ jar['foo'].should be == 'foo'
754
+ end
755
+ end
756
+
757
+ describe :value? do
758
+ it 'checks request cookies' do
759
+ cookies('foo=bar').value?('bar').should be_true
760
+ end
761
+
762
+ it 'checks response cookies' do
763
+ jar = cookies
764
+ jar[:foo] = 'bar'
765
+ jar.value?('bar').should be_true
766
+ end
767
+
768
+ it 'does not use deleted cookies' do
769
+ jar = cookies('foo=bar')
770
+ jar.delete :foo
771
+ jar.value?('bar').should_not be_true
772
+ end
773
+ end
774
+
775
+ describe :values do
776
+ it { cookies('foo=bar', 'bar=baz').values.sort.should be == ['bar', 'baz'] }
777
+ end
778
+
779
+ describe :values_at do
780
+ it { cookies('foo=bar', 'bar=baz').values_at('foo').should be == ['bar'] }
781
+ end
782
+ end