grape 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

@@ -36,6 +36,29 @@ describe Grape::Middleware::Formatter do
36
36
  end
37
37
  end
38
38
 
39
+ context 'error handling' do
40
+ let(:formatter) { stub(:formatter) }
41
+ before do
42
+ Grape::Formatter::Base.stub(:formatter_for) { formatter }
43
+ end
44
+
45
+ it 'rescues formatter-specific exceptions' do
46
+ formatter.stub(:call) { raise Grape::Exceptions::InvalidFormatter.new(String, 'xml') }
47
+
48
+ expect {
49
+ catch(:error){subject.call({'PATH_INFO' => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json'})}
50
+ }.to_not raise_error
51
+ end
52
+
53
+ it 'does not rescue other exceptions' do
54
+ formatter.stub(:call) { raise StandardError }
55
+
56
+ expect {
57
+ catch(:error){subject.call({'PATH_INFO' => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json'})}
58
+ }.to raise_error
59
+ end
60
+ end
61
+
39
62
  context 'detection' do
40
63
 
41
64
  it 'uses the extension if one is provided' do
@@ -166,6 +189,31 @@ describe Grape::Middleware::Formatter do
166
189
  end
167
190
  end
168
191
  end
192
+ it "parses the chunked body from #{method} and copies values into rack.request.from_hash" do
193
+ io = StringIO.new('{"is_boolean":true,"string":"thing"}')
194
+ subject.call({
195
+ 'PATH_INFO' => '/infol',
196
+ 'REQUEST_METHOD' => method,
197
+ 'CONTENT_TYPE' => 'application/json',
198
+ 'rack.input' => io,
199
+ 'HTTP_TRANSFER_ENCODING' => 'chunked'
200
+ })
201
+ subject.env['rack.request.form_hash']['is_boolean'].should be_true
202
+ subject.env['rack.request.form_hash']['string'].should == 'thing'
203
+ end
204
+ it "rewinds IO" do
205
+ io = StringIO.new('{"is_boolean":true,"string":"thing"}')
206
+ io.read
207
+ subject.call({
208
+ 'PATH_INFO' => '/infol',
209
+ 'REQUEST_METHOD' => method,
210
+ 'CONTENT_TYPE' => 'application/json',
211
+ 'rack.input' => io,
212
+ 'HTTP_TRANSFER_ENCODING' => 'chunked'
213
+ })
214
+ subject.env['rack.request.form_hash']['is_boolean'].should be_true
215
+ subject.env['rack.request.form_hash']['string'].should == 'thing'
216
+ end
169
217
  it 'parses the body from an xml #{method} and copies values into rack.request.from_hash' do
170
218
  io = StringIO.new('<thing><name>Test</name></thing>')
171
219
  subject.call({
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Middleware::Versioner::AcceptVersionHeader do
4
+ let(:app) { lambda{|env| [200, env, env]} }
5
+ subject { Grape::Middleware::Versioner::AcceptVersionHeader.new(app, @options || {}) }
6
+
7
+ before do
8
+ @options = {
9
+ :version_options => {
10
+ :using => :accept_version_header
11
+ },
12
+ }
13
+ end
14
+
15
+ context 'api.version' do
16
+ before do
17
+ @options[:versions] = ['v1']
18
+ end
19
+
20
+ it 'is set' do
21
+ status, _, env = subject.call('HTTP_ACCEPT_VERSION' => 'v1')
22
+ env['api.version'].should eql 'v1'
23
+ status.should == 200
24
+ end
25
+
26
+ it 'is set if format provided' do
27
+ status, _, env = subject.call('HTTP_ACCEPT_VERSION' => 'v1')
28
+ env['api.version'].should eql 'v1'
29
+ status.should == 200
30
+ end
31
+
32
+ it 'fails with 406 Not Acceptable if version is not supported' do
33
+ expect {
34
+ env = subject.call('HTTP_ACCEPT_VERSION' => 'v2').last
35
+ }.to throw_symbol(
36
+ :error,
37
+ :status => 406,
38
+ :headers => {'X-Cascade' => 'pass'},
39
+ :message => 'The requested version is not supported.'
40
+ )
41
+ end
42
+ end
43
+
44
+ it 'succeeds if :strict is not set' do
45
+ subject.call('HTTP_ACCEPT_VERSION' => '').first.should == 200
46
+ subject.call({}).first.should == 200
47
+ end
48
+
49
+ it 'succeeds if :strict is set to false' do
50
+ @options[:version_options][:strict] = false
51
+ subject.call('HTTP_ACCEPT_VERSION' => '').first.should == 200
52
+ subject.call({}).first.should == 200
53
+ end
54
+
55
+ context 'when :strict is set' do
56
+ before do
57
+ @options[:versions] = ['v1']
58
+ @options[:version_options][:strict] = true
59
+ end
60
+
61
+ it 'fails with 406 Not Acceptable if header is not set' do
62
+ expect {
63
+ env = subject.call({}).last
64
+ }.to throw_symbol(
65
+ :error,
66
+ :status => 406,
67
+ :headers => {'X-Cascade' => 'pass'},
68
+ :message => 'Accept-Version header must be set.'
69
+ )
70
+ end
71
+
72
+ it 'fails with 406 Not Acceptable if header is empty' do
73
+ expect {
74
+ env = subject.call('HTTP_ACCEPT_VERSION' => '').last
75
+ }.to throw_symbol(
76
+ :error,
77
+ :status => 406,
78
+ :headers => {'X-Cascade' => 'pass'},
79
+ :message => 'Accept-Version header must be set.'
80
+ )
81
+ end
82
+
83
+ it 'succeeds if proper header is set' do
84
+ subject.call('HTTP_ACCEPT_VERSION' => 'v1').first.should == 200
85
+ end
86
+ end
87
+
88
+ context 'when :strict and :cascade=>false are set' do
89
+ before do
90
+ @options[:versions] = ['v1']
91
+ @options[:version_options][:strict] = true
92
+ @options[:version_options][:cascade] = false
93
+ end
94
+
95
+ it 'fails with 406 Not Acceptable if header is not set' do
96
+ expect {
97
+ env = subject.call({}).last
98
+ }.to throw_symbol(
99
+ :error,
100
+ :status => 406,
101
+ :headers => {},
102
+ :message => 'Accept-Version header must be set.'
103
+ )
104
+ end
105
+
106
+ it 'fails with 406 Not Acceptable if header is empty' do
107
+ expect {
108
+ env = subject.call('HTTP_ACCEPT_VERSION' => '').last
109
+ }.to throw_symbol(
110
+ :error,
111
+ :status => 406,
112
+ :headers => {},
113
+ :message => 'Accept-Version header must be set.'
114
+ )
115
+ end
116
+
117
+ it 'succeeds if proper header is set' do
118
+ subject.call('HTTP_ACCEPT_VERSION' => 'v1').first.should == 200
119
+ end
120
+ end
121
+ end
@@ -16,4 +16,7 @@ describe Grape::Middleware::Versioner do
16
16
  klass.using(:param).should == Grape::Middleware::Versioner::Param
17
17
  end
18
18
 
19
- end
19
+ it 'recognizes :accept_version_header' do
20
+ klass.using(:accept_version_header).should == Grape::Middleware::Versioner::AcceptVersionHeader
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Validations::DefaultValidator do
4
+
5
+ module ValidationsSpec
6
+ module DefaultValidatorSpec
7
+ class API < Grape::API
8
+ default_format :json
9
+
10
+ params do
11
+ optional :id
12
+ optional :type, :default => 'default-type'
13
+ end
14
+ get '/' do
15
+ { :id => params[:id], :type => params[:type] }
16
+ end
17
+
18
+ params do
19
+ optional :type1, :default => 'default-type1'
20
+ optional :type2, :default => 'default-type2'
21
+ end
22
+ get '/user' do
23
+ { :type1 => params[:type1], :type2 => params[:type2] }
24
+ end
25
+
26
+ params do
27
+ requires :id
28
+ optional :type1, :default => 'default-type1'
29
+ optional :type2, :default => 'default-type2'
30
+ end
31
+
32
+ get '/message' do
33
+ { :id => params[:id], :type1 => params[:type1], :type2 => params[:type2] }
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def app
40
+ ValidationsSpec::DefaultValidatorSpec::API
41
+ end
42
+
43
+ it 'set default value for optional param' do
44
+ get("/")
45
+ last_response.status.should == 200
46
+ last_response.body.should == { :id => nil, :type => 'default-type' }.to_json
47
+ end
48
+
49
+ it 'set default values for optional params' do
50
+ get("/user")
51
+ last_response.status.should == 200
52
+ last_response.body.should == { :type1 => 'default-type1', :type2 => 'default-type2' }.to_json
53
+ end
54
+
55
+ it 'set default values for missing params in the request' do
56
+ get("/user?type2=value2")
57
+ last_response.status.should == 200
58
+ last_response.body.should == { :type1 => 'default-type1', :type2 => 'value2' }.to_json
59
+ end
60
+
61
+ it 'set default values for optional params and allow to use required fields in the same time' do
62
+ get("/message?id=1")
63
+ last_response.status.should == 200
64
+ last_response.body.should == { :id => '1', :type1 => 'default-type1', :type2 => 'default-type2' }.to_json
65
+ end
66
+ end
67
+
@@ -79,6 +79,15 @@ describe Grape::Validations do
79
79
  last_response.status.should == 200
80
80
  last_response.body.should == 'required works'
81
81
  end
82
+
83
+ it 'adds to declared parameters' do
84
+ subject.params {
85
+ group :items do
86
+ requires :key
87
+ end
88
+ }
89
+ subject.settings[:declared_params].should == [:items => [:key]]
90
+ end
82
91
  end
83
92
 
84
93
  context 'custom validation' do
@@ -11,7 +11,7 @@ shared_examples_for 'versioning' do
11
11
 
12
12
  it 'adds the prefix before the API version' do
13
13
  subject.format :txt
14
- subject.prefix 'api'
14
+ subject.prefix 'api'
15
15
  subject.version 'v1', macro_options
16
16
  subject.get :hello do
17
17
  "Version: #{request.env['api.version']}"
@@ -106,4 +106,16 @@ shared_examples_for 'versioning' do
106
106
  end
107
107
  end
108
108
  end
109
+
110
+ it 'does not overwrite version parameter with API version' do
111
+ subject.format :txt
112
+ subject.version 'v1', macro_options
113
+ subject.params { requires :version }
114
+ subject.get :api_version_with_version_param do
115
+ params[:version]
116
+ end
117
+ versioned_get '/api_version_with_version_param?version=1', 'v1', macro_options
118
+ last_response.body.should eql '1'
119
+ end
120
+
109
121
  end
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,7 @@ require 'rack/test'
14
14
  require 'pry'
15
15
  require 'base64'
16
16
  require 'cookiejar'
17
+ require 'json'
17
18
 
18
19
  Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file|
19
20
  require file
@@ -10,6 +10,8 @@ def versioned_path(options = {})
10
10
  File.join('/', options[:prefix] || '', options[:path])
11
11
  when :header
12
12
  File.join('/', options[:prefix] || '', options[:path])
13
+ when :accept_version_header
14
+ File.join('/', options[:prefix] || '', options[:path])
13
15
  else
14
16
  raise ArgumentError.new("unknown versioning strategy: #{options[:using]}")
15
17
  end
@@ -25,6 +27,10 @@ def versioned_headers(options)
25
27
  {
26
28
  'HTTP_ACCEPT' => "application/vnd.#{options[:vendor]}-#{options[:version]}+#{options[:format]}"
27
29
  }
30
+ when :accept_version_header
31
+ {
32
+ 'HTTP_ACCEPT_VERSION' => "#{options[:version]}"
33
+ }
28
34
  else
29
35
  raise ArgumentError.new("unknown versioning strategy: #{options[:using]}")
30
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-01 00:00:00.000000000 Z
12
+ date: 2013-06-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -308,6 +308,7 @@ files:
308
308
  - lib/grape/formatter/serializable_hash.rb
309
309
  - lib/grape/formatter/txt.rb
310
310
  - lib/grape/formatter/xml.rb
311
+ - lib/grape/http/request.rb
311
312
  - lib/grape/locale/en.yml
312
313
  - lib/grape/middleware/auth/basic.rb
313
314
  - lib/grape/middleware/auth/digest.rb
@@ -317,6 +318,7 @@ files:
317
318
  - lib/grape/middleware/filter.rb
318
319
  - lib/grape/middleware/formatter.rb
319
320
  - lib/grape/middleware/versioner.rb
321
+ - lib/grape/middleware/versioner/accept_version_header.rb
320
322
  - lib/grape/middleware/versioner/header.rb
321
323
  - lib/grape/middleware/versioner/param.rb
322
324
  - lib/grape/middleware/versioner/path.rb
@@ -330,6 +332,7 @@ files:
330
332
  - lib/grape/util/hash_stack.rb
331
333
  - lib/grape/validations.rb
332
334
  - lib/grape/validations/coerce.rb
335
+ - lib/grape/validations/default.rb
333
336
  - lib/grape/validations/presence.rb
334
337
  - lib/grape/validations/regexp.rb
335
338
  - lib/grape/version.rb
@@ -349,12 +352,14 @@ files:
349
352
  - spec/grape/middleware/error_spec.rb
350
353
  - spec/grape/middleware/exception_spec.rb
351
354
  - spec/grape/middleware/formatter_spec.rb
355
+ - spec/grape/middleware/versioner/accept_version_header_spec.rb
352
356
  - spec/grape/middleware/versioner/header_spec.rb
353
357
  - spec/grape/middleware/versioner/param_spec.rb
354
358
  - spec/grape/middleware/versioner/path_spec.rb
355
359
  - spec/grape/middleware/versioner_spec.rb
356
360
  - spec/grape/util/hash_stack_spec.rb
357
361
  - spec/grape/validations/coerce_spec.rb
362
+ - spec/grape/validations/default_spec.rb
358
363
  - spec/grape/validations/presence_spec.rb
359
364
  - spec/grape/validations/regexp_spec.rb
360
365
  - spec/grape/validations/zh-CN.yml
@@ -378,7 +383,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
378
383
  version: '0'
379
384
  segments:
380
385
  - 0
381
- hash: -2839578735981182036
386
+ hash: -683082835591277946
382
387
  required_rubygems_version: !ruby/object:Gem::Requirement
383
388
  none: false
384
389
  requirements:
@@ -387,7 +392,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
387
392
  version: '0'
388
393
  segments:
389
394
  - 0
390
- hash: -2839578735981182036
395
+ hash: -683082835591277946
391
396
  requirements: []
392
397
  rubyforge_project: grape
393
398
  rubygems_version: 1.8.25
@@ -411,12 +416,14 @@ test_files:
411
416
  - spec/grape/middleware/error_spec.rb
412
417
  - spec/grape/middleware/exception_spec.rb
413
418
  - spec/grape/middleware/formatter_spec.rb
419
+ - spec/grape/middleware/versioner/accept_version_header_spec.rb
414
420
  - spec/grape/middleware/versioner/header_spec.rb
415
421
  - spec/grape/middleware/versioner/param_spec.rb
416
422
  - spec/grape/middleware/versioner/path_spec.rb
417
423
  - spec/grape/middleware/versioner_spec.rb
418
424
  - spec/grape/util/hash_stack_spec.rb
419
425
  - spec/grape/validations/coerce_spec.rb
426
+ - spec/grape/validations/default_spec.rb
420
427
  - spec/grape/validations/presence_spec.rb
421
428
  - spec/grape/validations/regexp_spec.rb
422
429
  - spec/grape/validations/zh-CN.yml