sinatra-contrib 2.0.0.rc1 → 2.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +2 -1
- data/lib/sinatra/decompile.rb +5 -0
- data/lib/sinatra/runner.rb +155 -0
- data/lib/sinatra/webdav.rb +93 -0
- data/sinatra-contrib.gemspec +5 -199
- metadata +13 -175
- data/spec/capture_spec.rb +0 -100
- data/spec/config_file/key_value.yml +0 -7
- data/spec/config_file/key_value.yml.erb +0 -6
- data/spec/config_file/key_value_override.yml +0 -2
- data/spec/config_file/missing_env.yml +0 -4
- data/spec/config_file/with_envs.yml +0 -7
- data/spec/config_file/with_nested_envs.yml +0 -11
- data/spec/config_file_spec.rb +0 -76
- data/spec/content_for/different_key.erb +0 -1
- data/spec/content_for/different_key.erubis +0 -1
- data/spec/content_for/different_key.haml +0 -2
- data/spec/content_for/different_key.slim +0 -2
- data/spec/content_for/footer.erb +0 -3
- data/spec/content_for/footer.erubis +0 -3
- data/spec/content_for/footer.haml +0 -2
- data/spec/content_for/footer.slim +0 -2
- data/spec/content_for/layout.erb +0 -1
- data/spec/content_for/layout.erubis +0 -1
- data/spec/content_for/layout.haml +0 -1
- data/spec/content_for/layout.slim +0 -1
- data/spec/content_for/multiple_blocks.erb +0 -4
- data/spec/content_for/multiple_blocks.erubis +0 -4
- data/spec/content_for/multiple_blocks.haml +0 -8
- data/spec/content_for/multiple_blocks.slim +0 -8
- data/spec/content_for/multiple_yields.erb +0 -3
- data/spec/content_for/multiple_yields.erubis +0 -3
- data/spec/content_for/multiple_yields.haml +0 -3
- data/spec/content_for/multiple_yields.slim +0 -3
- data/spec/content_for/passes_values.erb +0 -1
- data/spec/content_for/passes_values.erubis +0 -1
- data/spec/content_for/passes_values.haml +0 -1
- data/spec/content_for/passes_values.slim +0 -1
- data/spec/content_for/same_key.erb +0 -1
- data/spec/content_for/same_key.erubis +0 -1
- data/spec/content_for/same_key.haml +0 -2
- data/spec/content_for/same_key.slim +0 -2
- data/spec/content_for/takes_values.erb +0 -1
- data/spec/content_for/takes_values.erubis +0 -1
- data/spec/content_for/takes_values.haml +0 -3
- data/spec/content_for/takes_values.slim +0 -3
- data/spec/content_for_spec.rb +0 -241
- data/spec/cookies_spec.rb +0 -826
- data/spec/custom_logger_spec.rb +0 -43
- data/spec/extension_spec.rb +0 -32
- data/spec/json_spec.rb +0 -115
- data/spec/link_header_spec.rb +0 -99
- data/spec/multi_route_spec.rb +0 -59
- data/spec/namespace/foo.erb +0 -1
- data/spec/namespace/nested/foo.erb +0 -1
- data/spec/namespace_spec.rb +0 -791
- data/spec/okjson.rb +0 -581
- data/spec/reloader/app.rb.erb +0 -40
- data/spec/reloader_spec.rb +0 -465
- data/spec/required_params_spec.rb +0 -68
- data/spec/respond_with/bar.erb +0 -1
- data/spec/respond_with/bar.json.erb +0 -1
- data/spec/respond_with/baz.yajl +0 -1
- data/spec/respond_with/foo.html.erb +0 -1
- data/spec/respond_with/not_html.sass +0 -2
- data/spec/respond_with_spec.rb +0 -317
- data/spec/spec_helper.rb +0 -7
- data/spec/streaming_spec.rb +0 -415
@@ -1,68 +0,0 @@
|
|
1
|
-
require_relative 'spec_helper'
|
2
|
-
|
3
|
-
describe Sinatra::RequiredParams do
|
4
|
-
context "#required_params" do
|
5
|
-
context "simple keys" do
|
6
|
-
before do
|
7
|
-
mock_app do
|
8
|
-
helpers Sinatra::RequiredParams
|
9
|
-
get('/') { required_params(:p1, :p2) }
|
10
|
-
end
|
11
|
-
end
|
12
|
-
it 'return 400 if required params do not exist' do
|
13
|
-
get('/')
|
14
|
-
expect(last_response.status).to eq(400)
|
15
|
-
end
|
16
|
-
it 'return 400 if required params do not exist partially' do
|
17
|
-
get('/', :p1 => 1)
|
18
|
-
expect(last_response.status).to eq(400)
|
19
|
-
end
|
20
|
-
it 'return 200 if required params exist' do
|
21
|
-
get('/', :p1 => 1, :p2 => 2)
|
22
|
-
expect(last_response.status).to eq(200)
|
23
|
-
end
|
24
|
-
it 'return 200 if required params exist with array' do
|
25
|
-
get('/', :p1 => 1, :p2 => [31, 32, 33])
|
26
|
-
expect(last_response.status).to eq(200)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
context "hash keys" do
|
30
|
-
before do
|
31
|
-
mock_app do
|
32
|
-
helpers Sinatra::RequiredParams
|
33
|
-
get('/') { required_params(:p1, :p2 => :p21) }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
it 'return 400 if required params do not exist' do
|
37
|
-
get('/')
|
38
|
-
expect(last_response.status).to eq(400)
|
39
|
-
end
|
40
|
-
it 'return 200 if required params exist' do
|
41
|
-
get('/', :p1 => 1, :p2 => {:p21 => 21})
|
42
|
-
expect(last_response.status).to eq(200)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
context "complex keys" do
|
46
|
-
before do
|
47
|
-
mock_app do
|
48
|
-
helpers Sinatra::RequiredParams
|
49
|
-
get('/') { required_params(:p1 => [:p11, {:p12 => :p121, :p122 => [:p123, {:p124 => :p1241}]}]) }
|
50
|
-
end
|
51
|
-
end
|
52
|
-
it 'return 400 if required params do not exist' do
|
53
|
-
get('/')
|
54
|
-
expect(last_response.status).to eq(400)
|
55
|
-
end
|
56
|
-
it 'return 200 if required params exist' do
|
57
|
-
get('/', :p1 => {:p11 => 11, :p12 => {:p121 => 121}, :p122 => {:p123 => 123, :p124 => {:p1241 => 1241}}})
|
58
|
-
expect(last_response.status).to eq(200)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "#_required_params" do
|
64
|
-
it "is invisible" do
|
65
|
-
expect { _required_params }.to raise_error(NameError)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/spec/respond_with/bar.erb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
guten Tag!
|
@@ -1 +0,0 @@
|
|
1
|
-
json!
|
data/spec/respond_with/baz.yajl
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
json = "yajl!"
|
@@ -1 +0,0 @@
|
|
1
|
-
Hello <%= name %>!
|
data/spec/respond_with_spec.rb
DELETED
@@ -1,317 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'okjson'
|
5
|
-
|
6
|
-
describe Sinatra::RespondWith do
|
7
|
-
def provides(*args)
|
8
|
-
@provides = args
|
9
|
-
end
|
10
|
-
|
11
|
-
def respond_app(&block)
|
12
|
-
types = @provides
|
13
|
-
mock_app do
|
14
|
-
set :app_file, __FILE__
|
15
|
-
set :views, root + '/respond_with'
|
16
|
-
register Sinatra::RespondWith
|
17
|
-
respond_to(*types) if types
|
18
|
-
class_eval(&block)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def respond_to(*args, &block)
|
23
|
-
respond_app { get('/') { respond_to(*args, &block) } }
|
24
|
-
end
|
25
|
-
|
26
|
-
def respond_with(*args, &block)
|
27
|
-
respond_app { get('/') { respond_with(*args, &block) } }
|
28
|
-
end
|
29
|
-
|
30
|
-
def req(*types)
|
31
|
-
p = types.shift if types.first.is_a? String and types.first.start_with? '/'
|
32
|
-
accept = types.map { |t| Sinatra::Base.mime_type(t).to_s }.join ','
|
33
|
-
get (p || '/'), {}, 'HTTP_ACCEPT' => accept
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "Helpers#respond_to" do
|
37
|
-
it 'allows defining handlers by file extensions' do
|
38
|
-
respond_to do |format|
|
39
|
-
format.html { "html!" }
|
40
|
-
format.json { "json!" }
|
41
|
-
end
|
42
|
-
|
43
|
-
expect(req(:html).body).to eq("html!")
|
44
|
-
expect(req(:json).body).to eq("json!")
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'respects quality' do
|
48
|
-
respond_to do |format|
|
49
|
-
format.html { "html!" }
|
50
|
-
format.json { "json!" }
|
51
|
-
end
|
52
|
-
|
53
|
-
expect(req("text/html;q=0.7, application/json;q=0.3").body).to eq("html!")
|
54
|
-
expect(req("text/html;q=0.3, application/json;q=0.7").body).to eq("json!")
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'allows using mime types' do
|
58
|
-
respond_to do |format|
|
59
|
-
format.on('text/html') { "html!" }
|
60
|
-
format.json { "json!" }
|
61
|
-
end
|
62
|
-
|
63
|
-
expect(req(:html).body).to eq("html!")
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'allows using wildcards in format matchers' do
|
67
|
-
respond_to do |format|
|
68
|
-
format.on('text/*') { "text!" }
|
69
|
-
format.json { "json!" }
|
70
|
-
end
|
71
|
-
|
72
|
-
expect(req(:html).body).to eq("text!")
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'allows using catch all wildcards in format matchers' do
|
76
|
-
respond_to do |format|
|
77
|
-
format.on('*/*') { "anything!" }
|
78
|
-
format.json { "json!" }
|
79
|
-
end
|
80
|
-
|
81
|
-
expect(req(:html).body).to eq("anything!")
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'prefers concret over generic' do
|
85
|
-
respond_to do |format|
|
86
|
-
format.on('text/*') { "text!" }
|
87
|
-
format.on('*/*') { "anything!" }
|
88
|
-
format.json { "json!" }
|
89
|
-
end
|
90
|
-
|
91
|
-
expect(req(:json).body).to eq("json!")
|
92
|
-
expect(req(:html).body).to eq("text!")
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'does not set up default handlers' do
|
96
|
-
respond_to
|
97
|
-
expect(req).not_to be_ok
|
98
|
-
expect(status).to eq(500)
|
99
|
-
expect(body).to eq("Unknown template engine")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
describe "Helpers#respond_with" do
|
104
|
-
describe "matching" do
|
105
|
-
it 'allows defining handlers by file extensions' do
|
106
|
-
respond_with(:ignore) do |format|
|
107
|
-
format.html { "html!" }
|
108
|
-
format.json { "json!" }
|
109
|
-
end
|
110
|
-
|
111
|
-
expect(req(:html).body).to eq("html!")
|
112
|
-
expect(req(:json).body).to eq("json!")
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'respects quality' do
|
116
|
-
respond_with(:ignore) do |format|
|
117
|
-
format.html { "html!" }
|
118
|
-
format.json { "json!" }
|
119
|
-
end
|
120
|
-
|
121
|
-
expect(req("text/html;q=0.7, application/json;q=0.3").body).to eq("html!")
|
122
|
-
expect(req("text/html;q=0.3, application/json;q=0.7").body).to eq("json!")
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'allows using mime types' do
|
126
|
-
respond_with(:ignore) do |format|
|
127
|
-
format.on('text/html') { "html!" }
|
128
|
-
format.json { "json!" }
|
129
|
-
end
|
130
|
-
|
131
|
-
expect(req(:html).body).to eq("html!")
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'allows using wildcards in format matchers' do
|
135
|
-
respond_with(:ignore) do |format|
|
136
|
-
format.on('text/*') { "text!" }
|
137
|
-
format.json { "json!" }
|
138
|
-
end
|
139
|
-
|
140
|
-
expect(req(:html).body).to eq("text!")
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'allows using catch all wildcards in format matchers' do
|
144
|
-
respond_with(:ignore) do |format|
|
145
|
-
format.on('*/*') { "anything!" }
|
146
|
-
format.json { "json!" }
|
147
|
-
end
|
148
|
-
|
149
|
-
expect(req(:html).body).to eq("anything!")
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'prefers concret over generic' do
|
153
|
-
respond_with(:ignore) do |format|
|
154
|
-
format.on('text/*') { "text!" }
|
155
|
-
format.on('*/*') { "anything!" }
|
156
|
-
format.json { "json!" }
|
157
|
-
end
|
158
|
-
|
159
|
-
expect(req(:json).body).to eq("json!")
|
160
|
-
expect(req(:html).body).to eq("text!")
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
describe "default behavior" do
|
165
|
-
it 'converts objects to json out of the box' do
|
166
|
-
respond_with 'a' => 'b'
|
167
|
-
expect(OkJson.decode(req(:json).body)).to eq({'a' => 'b'})
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'handles multiple routes correctly' do
|
171
|
-
respond_app do
|
172
|
-
get('/') { respond_with 'a' => 'b' }
|
173
|
-
get('/:name') { respond_with 'a' => params[:name] }
|
174
|
-
end
|
175
|
-
expect(OkJson.decode(req('/', :json).body)).to eq({'a' => 'b'})
|
176
|
-
expect(OkJson.decode(req('/b', :json).body)).to eq({'a' => 'b'})
|
177
|
-
expect(OkJson.decode(req('/c', :json).body)).to eq({'a' => 'c'})
|
178
|
-
end
|
179
|
-
|
180
|
-
it "calls to_EXT if available" do
|
181
|
-
respond_with Struct.new(:to_pdf).new("hello")
|
182
|
-
expect(req(:pdf).body).to eq("hello")
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'results in a 500 if format cannot be produced' do
|
186
|
-
respond_with({})
|
187
|
-
expect(req(:html)).not_to be_ok
|
188
|
-
expect(status).to eq(500)
|
189
|
-
expect(body).to eq("Unknown template engine")
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
describe 'templates' do
|
194
|
-
it 'looks for templates with name.target.engine' do
|
195
|
-
respond_with :foo, :name => 'World'
|
196
|
-
expect(req(:html)).to be_ok
|
197
|
-
expect(body).to eq("Hello World!")
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'looks for templates with name.engine for specific engines' do
|
201
|
-
respond_with :bar
|
202
|
-
expect(req(:html)).to be_ok
|
203
|
-
expect(body).to eq("guten Tag!")
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'does not use name.engine for engines producing other formats' do
|
207
|
-
respond_with :not_html
|
208
|
-
expect(req(:html)).not_to be_ok
|
209
|
-
expect(status).to eq(500)
|
210
|
-
expect(body).to eq("Unknown template engine")
|
211
|
-
end
|
212
|
-
|
213
|
-
it 'falls back to #json if no template is found' do
|
214
|
-
respond_with :foo, :name => 'World'
|
215
|
-
expect(req(:json)).to be_ok
|
216
|
-
expect(OkJson.decode(body)).to eq({'name' => 'World'})
|
217
|
-
end
|
218
|
-
|
219
|
-
it 'favors templates over #json' do
|
220
|
-
respond_with :bar, :name => 'World'
|
221
|
-
expect(req(:json)).to be_ok
|
222
|
-
expect(body).to eq('json!')
|
223
|
-
end
|
224
|
-
|
225
|
-
it 'falls back to to_EXT if no template is found' do
|
226
|
-
object = {:name => 'World'}
|
227
|
-
def object.to_pdf; "hi" end
|
228
|
-
respond_with :foo, object
|
229
|
-
expect(req(:pdf)).to be_ok
|
230
|
-
expect(body).to eq("hi")
|
231
|
-
end
|
232
|
-
|
233
|
-
unless defined? JRUBY_VERSION
|
234
|
-
it 'uses yajl for json' do
|
235
|
-
respond_with :baz
|
236
|
-
expect(req(:json)).to be_ok
|
237
|
-
expect(body).to eq("\"yajl!\"")
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
describe 'customizing' do
|
243
|
-
it 'allows customizing' do
|
244
|
-
respond_with(:foo, :name => 'World') { |f| f.html { 'html!' }}
|
245
|
-
expect(req(:html)).to be_ok
|
246
|
-
expect(body).to eq("html!")
|
247
|
-
end
|
248
|
-
|
249
|
-
it 'falls back to default behavior if none matches' do
|
250
|
-
respond_with(:foo, :name => 'World') { |f| f.json { 'json!' }}
|
251
|
-
expect(req(:html)).to be_ok
|
252
|
-
expect(body).to eq("Hello World!")
|
253
|
-
end
|
254
|
-
|
255
|
-
it 'favors generic rule over default behavior' do
|
256
|
-
respond_with(:foo, :name => 'World') { |f| f.on('*/*') { 'generic!' }}
|
257
|
-
expect(req(:html)).to be_ok
|
258
|
-
expect(body).to eq("generic!")
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe "inherited" do
|
263
|
-
it "registers RespondWith in an inherited app" do
|
264
|
-
app = Sinatra.new do
|
265
|
-
set :app_file, __FILE__
|
266
|
-
set :views, root + '/respond_with'
|
267
|
-
register Sinatra::RespondWith
|
268
|
-
|
269
|
-
get '/a' do
|
270
|
-
respond_with :json
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
self.app = Sinatra.new(app)
|
275
|
-
expect(req('/a', :json)).not_to be_ok
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
describe :respond_to do
|
281
|
-
it 'acts as global provides condition' do
|
282
|
-
respond_app do
|
283
|
-
respond_to :json, :html
|
284
|
-
get('/a') { 'ok' }
|
285
|
-
get('/b') { 'ok' }
|
286
|
-
end
|
287
|
-
|
288
|
-
expect(req('/b', :xml)).not_to be_ok
|
289
|
-
expect(req('/b', :html)).to be_ok
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'still allows provides' do
|
293
|
-
respond_app do
|
294
|
-
respond_to :json, :html
|
295
|
-
get('/a') { 'ok' }
|
296
|
-
get('/b', :provides => :json) { 'ok' }
|
297
|
-
end
|
298
|
-
|
299
|
-
expect(req('/b', :html)).not_to be_ok
|
300
|
-
expect(req('/b', :json)).to be_ok
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'plays well with namespaces' do
|
304
|
-
respond_app do
|
305
|
-
register Sinatra::Namespace
|
306
|
-
namespace '/a' do
|
307
|
-
respond_to :json
|
308
|
-
get { 'json' }
|
309
|
-
end
|
310
|
-
get('/b') { 'anything' }
|
311
|
-
end
|
312
|
-
|
313
|
-
expect(req('/a', :html)).not_to be_ok
|
314
|
-
expect(req('/b', :html)).to be_ok
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
data/spec/spec_helper.rb
DELETED
data/spec/streaming_spec.rb
DELETED
@@ -1,415 +0,0 @@
|
|
1
|
-
require 'backports'
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Sinatra::Streaming do
|
5
|
-
def stream(&block)
|
6
|
-
rack_middleware = @use
|
7
|
-
out = nil
|
8
|
-
mock_app do
|
9
|
-
rack_middleware.each { |args| use(*args) }
|
10
|
-
helpers Sinatra::Streaming
|
11
|
-
get('/') { out = stream(&block) }
|
12
|
-
end
|
13
|
-
get('/')
|
14
|
-
out
|
15
|
-
end
|
16
|
-
|
17
|
-
def use(*args)
|
18
|
-
@use << args
|
19
|
-
end
|
20
|
-
|
21
|
-
before do
|
22
|
-
@use = []
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'stream test helper' do
|
26
|
-
it 'runs the given block' do
|
27
|
-
ran = false
|
28
|
-
stream { ran = true }
|
29
|
-
expect(ran).to be true
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'returns the stream object' do
|
33
|
-
out = stream { }
|
34
|
-
expect(out).to be_a(Sinatra::Helpers::Stream)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'fires a request against that stream' do
|
38
|
-
stream { |out| out << "Hello World!" }
|
39
|
-
expect(last_response).to be_ok
|
40
|
-
expect(body).to eq("Hello World!")
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'passes the stream object to the block' do
|
44
|
-
passed = nil
|
45
|
-
returned = stream { |out| passed = out }
|
46
|
-
expect(passed).to eq(returned)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context Sinatra::Streaming::Stream do
|
51
|
-
it 'should extend the stream object' do
|
52
|
-
out = stream { }
|
53
|
-
expect(out).to be_a(Sinatra::Streaming::Stream)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should not extend stream objects of other apps' do
|
57
|
-
out = nil
|
58
|
-
mock_app { get('/') { out = stream { }}}
|
59
|
-
get('/')
|
60
|
-
expect(out).to be_a(Sinatra::Helpers::Stream)
|
61
|
-
expect(out).not_to be_a(Sinatra::Streaming::Stream)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'app' do
|
66
|
-
it 'is the app instance the stream was created from' do
|
67
|
-
out = stream { }
|
68
|
-
expect(out.app).to be_a(Sinatra::Base)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'lineno' do
|
73
|
-
it 'defaults to 0' do
|
74
|
-
expect(stream { }.lineno).to eq(0)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'does not increase on write' do
|
78
|
-
stream do |out|
|
79
|
-
out << "many\nlines\n"
|
80
|
-
expect(out.lineno).to eq(0)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'is writable' do
|
85
|
-
out = stream { }
|
86
|
-
out.lineno = 10
|
87
|
-
expect(out.lineno).to eq(10)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context 'pos' do
|
92
|
-
it 'defaults to 0' do
|
93
|
-
expect(stream { }.pos).to eq(0)
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'increases when writing data' do
|
97
|
-
stream do |out|
|
98
|
-
expect(out.pos).to eq(0)
|
99
|
-
out << 'hi'
|
100
|
-
expect(out.pos).to eq(2)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'is writable' do
|
105
|
-
out = stream { }
|
106
|
-
out.pos = 10
|
107
|
-
expect(out.pos).to eq(10)
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'aliased to #tell' do
|
111
|
-
out = stream { }
|
112
|
-
expect(out.tell).to eq(0)
|
113
|
-
out.pos = 10
|
114
|
-
expect(out.tell).to eq(10)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context 'closed' do
|
119
|
-
it 'returns false while streaming' do
|
120
|
-
stream { |out| expect(out).not_to be_closed }
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'returns true after streaming' do
|
124
|
-
expect(stream {}).to be_closed
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
context 'map!' do
|
129
|
-
it 'applies transformations later' do
|
130
|
-
stream do |out|
|
131
|
-
out.map! { |s| s.upcase }
|
132
|
-
out << 'ok'
|
133
|
-
end
|
134
|
-
expect(body).to eq("OK")
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'is chainable' do
|
138
|
-
stream do |out|
|
139
|
-
out.map! { |s| s.upcase }
|
140
|
-
out.map! { |s| s.reverse }
|
141
|
-
out << 'ok'
|
142
|
-
end
|
143
|
-
expect(body).to eq("KO")
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'works with middleware' do
|
147
|
-
middleware = Class.new do
|
148
|
-
def initialize(app) @app = app end
|
149
|
-
def call(env)
|
150
|
-
status, headers, body = @app.call(env)
|
151
|
-
body.map! { |s| s.upcase }
|
152
|
-
[status, headers, body]
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
use middleware
|
157
|
-
stream { |out| out << "ok" }
|
158
|
-
expect(body).to eq("OK")
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'modifies each value separately' do
|
162
|
-
stream do |out|
|
163
|
-
out.map! { |s| s.reverse }
|
164
|
-
out << "ab" << "cd"
|
165
|
-
end
|
166
|
-
expect(body).to eq("badc")
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
context 'map' do
|
171
|
-
it 'works with middleware' do
|
172
|
-
middleware = Class.new do
|
173
|
-
def initialize(app) @app = app end
|
174
|
-
def call(env)
|
175
|
-
status, headers, body = @app.call(env)
|
176
|
-
[status, headers, body.map(&:upcase)]
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
use middleware
|
181
|
-
stream { |out| out << "ok" }
|
182
|
-
expect(body).to eq("OK")
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'is chainable' do
|
186
|
-
middleware = Class.new do
|
187
|
-
def initialize(app) @app = app end
|
188
|
-
def call(env)
|
189
|
-
status, headers, body = @app.call(env)
|
190
|
-
[status, headers, body.map(&:upcase).map(&:reverse)]
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
use middleware
|
195
|
-
stream { |out| out << "ok" }
|
196
|
-
expect(body).to eq("KO")
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'can be written as each.map' do
|
200
|
-
middleware = Class.new do
|
201
|
-
def initialize(app) @app = app end
|
202
|
-
def call(env)
|
203
|
-
status, headers, body = @app.call(env)
|
204
|
-
[status, headers, body.each.map(&:upcase)]
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
use middleware
|
209
|
-
stream { |out| out << "ok" }
|
210
|
-
expect(body).to eq("OK")
|
211
|
-
end
|
212
|
-
|
213
|
-
it 'does not modify the original body' do
|
214
|
-
stream do |out|
|
215
|
-
out.map { |s| s.reverse }
|
216
|
-
out << 'ok'
|
217
|
-
end
|
218
|
-
expect(body).to eq('ok')
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
context 'write' do
|
223
|
-
it 'writes to the stream' do
|
224
|
-
stream { |out| out.write 'hi' }
|
225
|
-
expect(body).to eq('hi')
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'returns the number of bytes' do
|
229
|
-
stream do |out|
|
230
|
-
expect(out.write('hi')).to eq(2)
|
231
|
-
expect(out.write('hello')).to eq(5)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
it 'accepts non-string objects' do
|
236
|
-
stream do |out|
|
237
|
-
expect(out.write(12)).to eq(2)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
it 'should be aliased to syswrite' do
|
242
|
-
stream { |out| expect(out.syswrite('hi')).to eq(2) }
|
243
|
-
expect(body).to eq('hi')
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'should be aliased to write_nonblock' do
|
247
|
-
stream { |out| expect(out.write_nonblock('hi')).to eq(2) }
|
248
|
-
expect(body).to eq('hi')
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
context 'print' do
|
253
|
-
it 'writes to the stream' do
|
254
|
-
stream { |out| out.print('hi') }
|
255
|
-
expect(body).to eq('hi')
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'accepts multiple arguments' do
|
259
|
-
stream { |out| out.print(1, 2, 3, 4) }
|
260
|
-
expect(body).to eq('1234')
|
261
|
-
end
|
262
|
-
|
263
|
-
it 'returns nil' do
|
264
|
-
stream { |out| expect(out.print('hi')).to be_nil }
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
context 'printf' do
|
269
|
-
it 'writes to the stream' do
|
270
|
-
stream { |out| out.printf('hi') }
|
271
|
-
expect(body).to eq('hi')
|
272
|
-
end
|
273
|
-
|
274
|
-
it 'interpolates the format string' do
|
275
|
-
stream { |out| out.printf("%s: %d", "answer", 42) }
|
276
|
-
expect(body).to eq('answer: 42')
|
277
|
-
end
|
278
|
-
|
279
|
-
it 'returns nil' do
|
280
|
-
stream { |out| expect(out.printf('hi')).to be_nil }
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
context 'putc' do
|
285
|
-
it 'writes the first character of a string' do
|
286
|
-
stream { |out| out.putc('hi') }
|
287
|
-
expect(body).to eq('h')
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'writes the character corresponding to an integer' do
|
291
|
-
stream { |out| out.putc(42) }
|
292
|
-
expect(body).to eq('*')
|
293
|
-
end
|
294
|
-
|
295
|
-
it 'returns nil' do
|
296
|
-
stream { |out| expect(out.putc('hi')).to be_nil }
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
context 'puts' do
|
301
|
-
it 'writes to the stream' do
|
302
|
-
stream { |out| out.puts('hi') }
|
303
|
-
expect(body).to eq("hi\n")
|
304
|
-
end
|
305
|
-
|
306
|
-
it 'accepts multiple arguments' do
|
307
|
-
stream { |out| out.puts(1, 2, 3, 4) }
|
308
|
-
expect(body).to eq("1\n2\n3\n4\n")
|
309
|
-
end
|
310
|
-
|
311
|
-
it 'returns nil' do
|
312
|
-
stream { |out| expect(out.puts('hi')).to be_nil }
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
context 'close' do
|
317
|
-
it 'sets #closed? to true' do
|
318
|
-
stream do |out|
|
319
|
-
out.close
|
320
|
-
expect(out).to be_closed
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
it 'sets #closed_write? to true' do
|
325
|
-
stream do |out|
|
326
|
-
expect(out).not_to be_closed_write
|
327
|
-
out.close
|
328
|
-
expect(out).to be_closed_write
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
it 'fires callbacks' do
|
333
|
-
stream do |out|
|
334
|
-
fired = false
|
335
|
-
out.callback { fired = true }
|
336
|
-
out.close
|
337
|
-
expect(fired).to be true
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
it 'prevents from further writing' do
|
342
|
-
stream do |out|
|
343
|
-
out.close
|
344
|
-
expect { out << 'hi' }.to raise_error(IOError, 'not opened for writing')
|
345
|
-
end
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
context 'close_read' do
|
350
|
-
it 'raises the appropriate exception' do
|
351
|
-
expect { stream { |out| out.close_read }}.
|
352
|
-
to raise_error(IOError, "closing non-duplex IO for reading")
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
context 'closed_read?' do
|
357
|
-
it('returns true') { stream { |out| expect(out).to be_closed_read }}
|
358
|
-
end
|
359
|
-
|
360
|
-
context 'rewind' do
|
361
|
-
it 'resets pos' do
|
362
|
-
stream do |out|
|
363
|
-
out << 'hi'
|
364
|
-
out.rewind
|
365
|
-
expect(out.pos).to eq(0)
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
it 'resets lineno' do
|
370
|
-
stream do |out|
|
371
|
-
out.lineno = 10
|
372
|
-
out.rewind
|
373
|
-
expect(out.lineno).to eq(0)
|
374
|
-
end
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
raises = %w[
|
379
|
-
bytes eof? eof getbyte getc gets read read_nonblock readbyte readchar
|
380
|
-
readline readlines readpartial sysread ungetbyte ungetc
|
381
|
-
]
|
382
|
-
|
383
|
-
enum = %w[chars each_line each_byte each_char lines]
|
384
|
-
dummies = %w[flush fsync internal_encoding pid]
|
385
|
-
|
386
|
-
raises.each do |method|
|
387
|
-
context method do
|
388
|
-
it 'raises the appropriate exception' do
|
389
|
-
expect { stream { |out| out.public_send(method) }}.
|
390
|
-
to raise_error(IOError, "not opened for reading")
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
enum.each do |method|
|
396
|
-
context method do
|
397
|
-
it 'creates an Enumerator' do
|
398
|
-
stream { |out| expect(out.public_send(method)).to be_a(Enumerator) }
|
399
|
-
end
|
400
|
-
|
401
|
-
it 'calling each raises the appropriate exception' do
|
402
|
-
expect { stream { |out| out.public_send(method).each { }}}.
|
403
|
-
to raise_error(IOError, "not opened for reading")
|
404
|
-
end
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
dummies.each do |method|
|
409
|
-
context method do
|
410
|
-
it 'returns nil' do
|
411
|
-
stream { |out| expect(out.public_send(method)).to be_nil }
|
412
|
-
end
|
413
|
-
end
|
414
|
-
end
|
415
|
-
end
|