rubycut-sinatra-contrib 1.4.0

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