grape 0.3.0 → 0.7.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.

Files changed (101) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +70 -0
  4. data/.travis.yml +7 -6
  5. data/CHANGELOG.md +134 -4
  6. data/CONTRIBUTING.md +118 -0
  7. data/Gemfile +5 -2
  8. data/README.md +551 -116
  9. data/RELEASING.md +105 -0
  10. data/Rakefile +29 -8
  11. data/UPGRADING.md +124 -0
  12. data/grape.gemspec +3 -3
  13. data/lib/grape/api.rb +207 -88
  14. data/lib/grape/cookies.rb +4 -8
  15. data/lib/grape/endpoint.rb +198 -144
  16. data/lib/grape/error_formatter/base.rb +5 -7
  17. data/lib/grape/error_formatter/json.rb +3 -5
  18. data/lib/grape/error_formatter/txt.rb +1 -3
  19. data/lib/grape/error_formatter/xml.rb +4 -6
  20. data/lib/grape/exceptions/base.rb +9 -9
  21. data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
  22. data/lib/grape/exceptions/invalid_formatter.rb +1 -4
  23. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -5
  24. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -6
  25. data/lib/grape/exceptions/missing_mime_type.rb +1 -5
  26. data/lib/grape/exceptions/missing_option.rb +1 -4
  27. data/lib/grape/exceptions/missing_vendor_option.rb +1 -4
  28. data/lib/grape/exceptions/unknown_options.rb +1 -5
  29. data/lib/grape/exceptions/unknown_validator.rb +1 -3
  30. data/lib/grape/exceptions/validation.rb +13 -3
  31. data/lib/grape/exceptions/validation_errors.rb +43 -0
  32. data/lib/grape/formatter/base.rb +5 -7
  33. data/lib/grape/formatter/json.rb +0 -3
  34. data/lib/grape/formatter/serializable_hash.rb +15 -15
  35. data/lib/grape/formatter/txt.rb +0 -2
  36. data/lib/grape/formatter/xml.rb +0 -2
  37. data/lib/grape/http/request.rb +26 -0
  38. data/lib/grape/locale/en.yml +8 -5
  39. data/lib/grape/middleware/auth/base.rb +30 -0
  40. data/lib/grape/middleware/auth/basic.rb +3 -20
  41. data/lib/grape/middleware/auth/digest.rb +2 -19
  42. data/lib/grape/middleware/auth/oauth2.rb +31 -24
  43. data/lib/grape/middleware/base.rb +7 -7
  44. data/lib/grape/middleware/error.rb +36 -22
  45. data/lib/grape/middleware/filter.rb +3 -3
  46. data/lib/grape/middleware/formatter.rb +99 -61
  47. data/lib/grape/middleware/globals.rb +13 -0
  48. data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
  49. data/lib/grape/middleware/versioner/header.rb +22 -16
  50. data/lib/grape/middleware/versioner/param.rb +9 -11
  51. data/lib/grape/middleware/versioner/path.rb +10 -13
  52. data/lib/grape/middleware/versioner.rb +3 -1
  53. data/lib/grape/namespace.rb +23 -0
  54. data/lib/grape/parser/base.rb +3 -5
  55. data/lib/grape/parser/json.rb +0 -2
  56. data/lib/grape/parser/xml.rb +0 -2
  57. data/lib/grape/path.rb +70 -0
  58. data/lib/grape/route.rb +10 -6
  59. data/lib/grape/util/content_types.rb +2 -1
  60. data/lib/grape/util/deep_merge.rb +5 -5
  61. data/lib/grape/util/hash_stack.rb +13 -2
  62. data/lib/grape/validations/coerce.rb +11 -10
  63. data/lib/grape/validations/default.rb +25 -0
  64. data/lib/grape/validations/presence.rb +7 -3
  65. data/lib/grape/validations/regexp.rb +2 -5
  66. data/lib/grape/validations/values.rb +17 -0
  67. data/lib/grape/validations.rb +161 -54
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +19 -4
  70. data/spec/grape/api_spec.rb +897 -268
  71. data/spec/grape/endpoint_spec.rb +283 -66
  72. data/spec/grape/entity_spec.rb +132 -29
  73. data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
  74. data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
  75. data/spec/grape/middleware/auth/basic_spec.rb +8 -8
  76. data/spec/grape/middleware/auth/digest_spec.rb +5 -5
  77. data/spec/grape/middleware/auth/oauth2_spec.rb +81 -36
  78. data/spec/grape/middleware/base_spec.rb +8 -13
  79. data/spec/grape/middleware/error_spec.rb +13 -17
  80. data/spec/grape/middleware/exception_spec.rb +47 -27
  81. data/spec/grape/middleware/formatter_spec.rb +103 -41
  82. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
  83. data/spec/grape/middleware/versioner/header_spec.rb +76 -51
  84. data/spec/grape/middleware/versioner/param_spec.rb +18 -18
  85. data/spec/grape/middleware/versioner/path_spec.rb +6 -6
  86. data/spec/grape/middleware/versioner_spec.rb +5 -2
  87. data/spec/grape/path_spec.rb +229 -0
  88. data/spec/grape/util/hash_stack_spec.rb +31 -32
  89. data/spec/grape/validations/coerce_spec.rb +116 -51
  90. data/spec/grape/validations/default_spec.rb +123 -0
  91. data/spec/grape/validations/presence_spec.rb +42 -44
  92. data/spec/grape/validations/regexp_spec.rb +9 -9
  93. data/spec/grape/validations/values_spec.rb +138 -0
  94. data/spec/grape/validations/zh-CN.yml +4 -3
  95. data/spec/grape/validations_spec.rb +681 -48
  96. data/spec/shared/versioning_examples.rb +22 -6
  97. data/spec/spec_helper.rb +3 -2
  98. data/spec/support/basic_auth_encode_helpers.rb +0 -1
  99. data/spec/support/content_type_helpers.rb +11 -0
  100. data/spec/support/versioned_helpers.rb +13 -5
  101. metadata +34 -84
@@ -3,13 +3,16 @@ require 'grape_entity'
3
3
 
4
4
  describe Grape::Entity do
5
5
  subject { Class.new(Grape::API) }
6
- def app; subject end
6
+
7
+ def app
8
+ subject
9
+ end
7
10
 
8
11
  describe '#present' do
9
12
  it 'sets the object as the body if no options are provided' do
10
13
  subject.get '/example' do
11
- present({:abc => 'def'})
12
- body.should == {:abc => 'def'}
14
+ present(abc: 'def')
15
+ body.should == { abc: 'def' }
13
16
  end
14
17
  get '/example'
15
18
  end
@@ -18,16 +21,16 @@ describe Grape::Entity do
18
21
  subject.get '/example' do
19
22
  entity_mock = Object.new
20
23
  entity_mock.should_receive(:represent)
21
- present Object.new, :with => entity_mock
24
+ present Object.new, with: entity_mock
22
25
  end
23
26
  get '/example'
24
27
  end
25
28
 
26
29
  it 'pulls a representation from the class options if it exists' do
27
30
  entity = Class.new(Grape::Entity)
28
- entity.stub!(:represent).and_return("Hiya")
31
+ entity.stub(:represent).and_return("Hiya")
29
32
 
30
- subject.represent Object, :with => entity
33
+ subject.represent Object, with: entity
31
34
  subject.get '/example' do
32
35
  present Object.new
33
36
  end
@@ -37,25 +40,40 @@ describe Grape::Entity do
37
40
 
38
41
  it 'pulls a representation from the class options if the presented object is a collection of objects' do
39
42
  entity = Class.new(Grape::Entity)
40
- entity.stub!(:represent).and_return("Hiya")
43
+ entity.stub(:represent).and_return("Hiya")
41
44
 
42
- class TestObject; end
45
+ class TestObject
46
+ end
43
47
 
44
- subject.represent TestObject, :with => entity
48
+ class FakeCollection
49
+ def first
50
+ TestObject.new
51
+ end
52
+ end
53
+
54
+ subject.represent TestObject, with: entity
45
55
  subject.get '/example' do
46
56
  present [TestObject.new]
47
57
  end
58
+
59
+ subject.get '/example2' do
60
+ present FakeCollection.new
61
+ end
62
+
48
63
  get '/example'
49
64
  last_response.body.should == "Hiya"
65
+
66
+ get '/example2'
67
+ last_response.body.should == "Hiya"
50
68
  end
51
69
 
52
70
  it 'pulls a representation from the class ancestor if it exists' do
53
71
  entity = Class.new(Grape::Entity)
54
- entity.stub!(:represent).and_return("Hiya")
72
+ entity.stub(:represent).and_return("Hiya")
55
73
 
56
74
  subclass = Class.new(Object)
57
75
 
58
- subject.represent Object, :with => entity
76
+ subject.represent Object, with: entity
59
77
  subject.get '/example' do
60
78
  present subclass.new
61
79
  end
@@ -66,7 +84,7 @@ describe Grape::Entity do
66
84
  it 'automatically uses Klass::Entity if that exists' do
67
85
  some_model = Class.new
68
86
  entity = Class.new(Grape::Entity)
69
- entity.stub!(:represent).and_return("Auto-detect!")
87
+ entity.stub(:represent).and_return("Auto-detect!")
70
88
 
71
89
  some_model.const_set :Entity, entity
72
90
 
@@ -80,7 +98,7 @@ describe Grape::Entity do
80
98
  it 'automatically uses Klass::Entity based on the first object in the collection being presented' do
81
99
  some_model = Class.new
82
100
  entity = Class.new(Grape::Entity)
83
- entity.stub!(:represent).and_return("Auto-detect!")
101
+ entity.stub(:represent).and_return("Auto-detect!")
84
102
 
85
103
  some_model.const_set :Entity, entity
86
104
 
@@ -91,15 +109,40 @@ describe Grape::Entity do
91
109
  last_response.body.should == 'Auto-detect!'
92
110
  end
93
111
 
112
+ it 'does not run autodetection for Entity when explicitely provided' do
113
+ entity = Class.new(Grape::Entity)
114
+ some_array = Array.new
115
+
116
+ subject.get '/example' do
117
+ present some_array, with: entity
118
+ end
119
+
120
+ some_array.should_not_receive(:first)
121
+ get '/example'
122
+ end
123
+
124
+ it 'autodetection does not use Entity if it is not a presenter' do
125
+ some_model = Class.new
126
+ entity = Class.new
127
+
128
+ some_model.class.const_set :Entity, entity
129
+
130
+ subject.get '/example' do
131
+ present some_model
132
+ end
133
+ get '/example'
134
+ entity.should_not_receive(:represent)
135
+ end
136
+
94
137
  it 'adds a root key to the output if one is given' do
95
138
  subject.get '/example' do
96
- present({:abc => 'def'}, :root => :root)
97
- body.should == {:root => {:abc => 'def'}}
139
+ present({ abc: 'def' }, root: :root)
140
+ body.should == { root: { abc: 'def' } }
98
141
  end
99
142
  get '/example'
100
143
  end
101
144
 
102
- [ :json, :serializable_hash ].each do |format|
145
+ [:json, :serializable_hash].each do |format|
103
146
 
104
147
  it 'presents with #{format}' do
105
148
  entity = Class.new(Grape::Entity)
@@ -114,7 +157,7 @@ describe Grape::Entity do
114
157
  @id = id
115
158
  end
116
159
  end
117
- present c.new(1), :with => entity
160
+ present c.new(1), with: entity
118
161
  end
119
162
 
120
163
  get '/example'
@@ -135,8 +178,8 @@ describe Grape::Entity do
135
178
  @id = id
136
179
  end
137
180
  end
138
- examples = [ c.new(1), c.new(2) ]
139
- present examples, :with => entity
181
+ examples = [c.new(1), c.new(2)]
182
+ present examples, with: entity
140
183
  end
141
184
 
142
185
  get '/examples'
@@ -146,21 +189,21 @@ describe Grape::Entity do
146
189
 
147
190
  end
148
191
 
149
- it 'presents with xml' do
192
+ it 'presents with xml' do
150
193
  entity = Class.new(Grape::Entity)
151
194
  entity.root "examples", "example"
152
195
  entity.expose :name
153
196
 
154
197
  subject.format :xml
155
198
 
156
- subject.get '/example' do
157
- c = Class.new do
199
+ subject.get '/example' do
200
+ c = Class.new do
158
201
  attr_reader :name
159
202
  def initialize(args)
160
203
  @name = args[:name] || "no name set"
161
204
  end
162
205
  end
163
- present c.new({:name => "johnnyiller"}), :with => entity
206
+ present c.new(name: "johnnyiller"), with: entity
164
207
  end
165
208
  get '/example'
166
209
  last_response.status.should == 200
@@ -175,27 +218,87 @@ describe Grape::Entity do
175
218
  XML
176
219
  end
177
220
 
178
- it 'presents with json' do
221
+ it 'presents with json' do
179
222
  entity = Class.new(Grape::Entity)
180
223
  entity.root "examples", "example"
181
224
  entity.expose :name
182
225
 
183
226
  subject.format :json
184
227
 
185
- subject.get '/example' do
186
- c = Class.new do
228
+ subject.get '/example' do
229
+ c = Class.new do
187
230
  attr_reader :name
188
231
  def initialize(args)
189
232
  @name = args[:name] || "no name set"
190
233
  end
191
234
  end
192
- present c.new({:name => "johnnyiller"}), :with => entity
235
+ present c.new(name: "johnnyiller"), with: entity
193
236
  end
194
237
  get '/example'
195
238
  last_response.status.should == 200
196
239
  last_response.headers['Content-type'].should == "application/json"
197
240
  last_response.body.should == '{"example":{"name":"johnnyiller"}}'
198
241
  end
199
- end
200
242
 
201
- end
243
+ it 'presents with jsonp utilising Rack::JSONP' do
244
+ require 'rack/contrib'
245
+
246
+ # Include JSONP middleware
247
+ subject.use Rack::JSONP
248
+
249
+ entity = Class.new(Grape::Entity)
250
+ entity.root "examples", "example"
251
+ entity.expose :name
252
+
253
+ # Rack::JSONP expects a standard JSON response
254
+ subject.format :json
255
+
256
+ subject.get '/example' do
257
+ c = Class.new do
258
+ attr_reader :name
259
+ def initialize(args)
260
+ @name = args[:name] || "no name set"
261
+ end
262
+ end
263
+
264
+ present c.new(name: "johnnyiller"), with: entity
265
+ end
266
+
267
+ get '/example?callback=abcDef'
268
+ last_response.status.should == 200
269
+ last_response.headers['Content-type'].should == "application/javascript"
270
+ last_response.body.should == 'abcDef({"example":{"name":"johnnyiller"}})'
271
+ end
272
+
273
+ context "present with multiple entities" do
274
+ it "present with multiple entities using optional symbol" do
275
+ user = Class.new do
276
+ attr_reader :name
277
+ def initialize(args)
278
+ @name = args[:name] || "no name set"
279
+ end
280
+ end
281
+ user1 = user.new(name: 'user1')
282
+ user2 = user.new(name: 'user2')
283
+
284
+ entity = Class.new(Grape::Entity)
285
+ entity.expose :name
286
+
287
+ subject.format :json
288
+ subject.get '/example' do
289
+ present :page, 1
290
+ present :user1, user1, with: entity
291
+ present :user2, user2, with: entity
292
+ end
293
+ get '/example'
294
+ expect_response_json = {
295
+ "page" => 1,
296
+ "user1" => { "name" => "user1" },
297
+ "user2" => { "name" => "user2" }
298
+ }
299
+ JSON(last_response.body).should == expect_response_json
300
+ end
301
+
302
+ end
303
+ end
304
+ end
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
1
  require 'spec_helper'
2
+
3
3
  describe Grape::Exceptions::MissingMimeType do
4
4
  describe "#message" do
5
5
 
@@ -8,17 +8,11 @@ describe Grape::Exceptions::MissingMimeType do
8
8
  end
9
9
 
10
10
  it "contains the problem in the message" do
11
- error.message.should include(
12
- "missing mime type for new_json"
13
- )
11
+ error.message.should include "missing mime type for new_json"
14
12
  end
15
13
 
16
14
  it "contains the resolution in the message" do
17
- error.message.should include(
18
- "or add your own with content_type :new_json, 'application/new_json' "
19
- )
15
+ error.message.should include "or add your own with content_type :new_json, 'application/new_json' "
20
16
  end
21
17
  end
22
-
23
-
24
18
  end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe Grape::Exceptions::ValidationErrors do
5
+ let(:validation_message) { "FooBar is invalid" }
6
+ let(:validation_error) { OpenStruct.new(param: validation_message) }
7
+
8
+ context "message" do
9
+ context "is not repeated" do
10
+ let(:error) do
11
+ described_class.new(errors: [validation_error, validation_error])
12
+ end
13
+ subject(:message) { error.message.split(',').map(&:strip) }
14
+
15
+ it { expect(message).to include validation_message }
16
+ it { expect(message.size).to eq 1 }
17
+ end
18
+ end
19
+ end
@@ -6,26 +6,26 @@ describe Grape::Middleware::Auth::Basic do
6
6
  def app
7
7
  Rack::Builder.new do |b|
8
8
  b.use Grape::Middleware::Error
9
- b.use(Grape::Middleware::Auth::Basic) do |u,p|
9
+ b.use(Grape::Middleware::Auth::Basic) do |u, p|
10
10
  u && p && u == p
11
11
  end
12
- b.run lambda{|env| [200, {}, ["Hello there."]]}
12
+ b.run lambda { |env| [200, {}, ["Hello there."]] }
13
13
  end
14
14
  end
15
-
15
+
16
16
  it 'throws a 401 if no auth is given' do
17
- @proc = lambda{ false }
17
+ @proc = lambda { false }
18
18
  get '/whatever'
19
19
  last_response.status.should == 401
20
20
  end
21
-
21
+
22
22
  it 'authenticates if given valid creds' do
23
- get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin','admin')
23
+ get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin', 'admin')
24
24
  last_response.status.should == 200
25
25
  end
26
-
26
+
27
27
  it 'throws a 401 is wrong auth is given' do
28
- get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin','wrong')
28
+ get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin', 'wrong')
29
29
  last_response.status.should == 401
30
30
  end
31
31
  end
@@ -9,12 +9,12 @@ RSpec::Matchers.define :be_challenge do
9
9
  end
10
10
 
11
11
  class Test < Grape::API
12
- http_digest({:realm => 'Test Api', :opaque => 'secret'}) do |username|
13
- {'foo' => 'bar'}[username]
12
+ http_digest(realm: 'Test Api', opaque: 'secret') do |username|
13
+ { 'foo' => 'bar' }[username]
14
14
  end
15
15
 
16
16
  get '/test' do
17
- [{:hey => 'you'},{:there => 'bar'},{:foo => 'baz'}]
17
+ [{ hey: 'you' }, { there: 'bar' }, { foo: 'baz' }]
18
18
  end
19
19
  end
20
20
 
@@ -22,12 +22,12 @@ describe Grape::Middleware::Auth::Digest do
22
22
  def app
23
23
  Test
24
24
  end
25
-
25
+
26
26
  it 'is a digest authentication challenge' do
27
27
  get '/test'
28
28
  last_response.should be_challenge
29
29
  end
30
-
30
+
31
31
  it 'throws a 401 if no auth is given' do
32
32
  get '/test'
33
33
  last_response.status.should == 401
@@ -2,89 +2,134 @@ require 'spec_helper'
2
2
 
3
3
  describe Grape::Middleware::Auth::OAuth2 do
4
4
  class FakeToken
5
+ attr_accessor :token
6
+
5
7
  def self.verify(token)
6
- FakeToken.new(token) if %w(g e).include?(token[0..0])
8
+ FakeToken.new(token) if !!token && %w(g e).include?(token[0..0])
7
9
  end
8
-
10
+
9
11
  def initialize(token)
10
- self.token = token
12
+ @token = token
11
13
  end
12
-
14
+
13
15
  def expired?
14
- self.token[0..0] == 'e'
16
+ @token[0..0] == 'e'
15
17
  end
16
-
18
+
17
19
  def permission_for?(env)
18
20
  env['PATH_INFO'] == '/forbidden' ? false : true
19
21
  end
20
-
21
- attr_accessor :token
22
22
  end
23
23
 
24
24
  def app
25
25
  Rack::Builder.app do
26
- use Grape::Middleware::Auth::OAuth2, :token_class => 'FakeToken'
27
- run lambda{|env| [200, {}, [ (env['api.token'].token rescue '') ]]}
26
+ use Grape::Middleware::Auth::OAuth2, token_class: 'FakeToken'
27
+ run lambda { |env| [200, {}, [(env['api.token'].token if env['api.token'])]] }
28
28
  end
29
29
  end
30
-
30
+
31
31
  context 'with the token in the query string' do
32
32
  context 'and a valid token' do
33
- before { get '/awesome?oauth_token=g123' }
34
-
33
+ before { get '/awesome?access_token=g123' }
34
+
35
35
  it 'sets env["api.token"]' do
36
36
  last_response.body.should == 'g123'
37
37
  end
38
38
  end
39
-
39
+
40
40
  context 'and an invalid token' do
41
41
  before do
42
42
  @err = catch :error do
43
- get '/awesome?oauth_token=b123'
43
+ get '/awesome?access_token=b123'
44
44
  end
45
45
  end
46
-
46
+
47
47
  it 'throws an error' do
48
48
  @err[:status].should == 401
49
49
  end
50
-
50
+
51
51
  it 'sets the WWW-Authenticate header in the response' do
52
- @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='invalid_token'"
52
+ @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='invalid_grant'"
53
53
  end
54
54
  end
55
55
  end
56
-
56
+
57
57
  context 'with an expired token' do
58
58
  before do
59
59
  @err = catch :error do
60
- get '/awesome?oauth_token=e123'
60
+ get '/awesome?access_token=e123'
61
61
  end
62
62
  end
63
-
64
- it { @err[:status].should == 401 }
65
- it { @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='expired_token'" }
63
+
64
+ it 'throws an error' do
65
+ @err[:status].should == 401
66
+ end
67
+
68
+ it 'sets the WWW-Authenticate header in the response to error' do
69
+ @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='invalid_grant'"
70
+ end
66
71
  end
67
-
68
- %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION).each do |head|
69
- context 'with the token in the #{head} header' do
70
- before { get '/awesome', {}, head => 'OAuth g123' }
71
- it { last_response.body.should == 'g123' }
72
+
73
+ %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION).each do |head|
74
+ context "with the token in the #{head} header" do
75
+ before do
76
+ get '/awesome', {}, head => 'OAuth g123'
77
+ end
78
+
79
+ it 'sets env["api.token"]' do
80
+ last_response.body.should == 'g123'
81
+ end
72
82
  end
73
83
  end
74
-
84
+
75
85
  context 'with the token in the POST body' do
76
- before { post '/awesome', {'oauth_token' => 'g123'} }
77
- it { last_response.body.should == 'g123'}
86
+ before do
87
+ post '/awesome', 'access_token' => 'g123'
88
+ end
89
+
90
+ it 'sets env["api.token"]' do
91
+ last_response.body.should == 'g123'
92
+ end
78
93
  end
79
-
94
+
80
95
  context 'when accessing something outside its scope' do
81
96
  before do
82
97
  @err = catch :error do
83
- get '/forbidden?oauth_token=g123'
98
+ get '/forbidden?access_token=g123'
99
+ end
100
+ end
101
+
102
+ it 'throws an error' do
103
+ @err[:status].should == 403
104
+ end
105
+
106
+ it 'sets the WWW-Authenticate header in the response to error' do
107
+ @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='insufficient_scope'"
108
+ end
109
+ end
110
+
111
+ context 'when authorization is not required' do
112
+ def app
113
+ Rack::Builder.app do
114
+ use Grape::Middleware::Auth::OAuth2, token_class: 'FakeToken', required: false
115
+ run lambda { |env| [200, {}, [(env['api.token'].token if env['api.token'])]] }
116
+ end
117
+ end
118
+
119
+ context 'with no token' do
120
+ before { post '/awesome' }
121
+
122
+ it 'succeeds anyway' do
123
+ last_response.status.should == 200
124
+ end
125
+ end
126
+
127
+ context 'with a valid token' do
128
+ before { get '/awesome?access_token=g123' }
129
+
130
+ it 'sets env["api.token"]' do
131
+ last_response.body.should == 'g123'
84
132
  end
85
133
  end
86
-
87
- it { @err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='insufficient_scope'" }
88
- it { @err[:status].should == 403 }
89
134
  end
90
135
  end
@@ -1,23 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Grape::Middleware::Base do
4
- subject { Grape::Middleware::Base.new( blank_app) }
5
- let(:blank_app) { lambda{|_| [200, {}, 'Hi there.']} }
4
+ subject { Grape::Middleware::Base.new(blank_app) }
5
+ let(:blank_app) { lambda { |_| [200, {}, 'Hi there.'] } }
6
6
 
7
7
  before do
8
8
  # Keep it one object for testing.
9
- subject.stub!(:dup).and_return(subject)
9
+ subject.stub(:dup).and_return(subject)
10
10
  end
11
11
 
12
12
  it 'has the app as an accessor' do
13
13
  subject.app.should == blank_app
14
14
  end
15
15
 
16
- it 'is able to access the request' do
17
- subject.call({})
18
- subject.request.should be_kind_of(Rack::Request)
19
- end
20
-
21
16
  it 'calls through to the app' do
22
17
  subject.call({}).should == [200, {}, 'Hi there.']
23
18
  end
@@ -31,7 +26,7 @@ describe Grape::Middleware::Base do
31
26
  subject.should_receive(:after)
32
27
  end
33
28
 
34
- after{ subject.call!({}) }
29
+ after { subject.call!({}) }
35
30
  end
36
31
 
37
32
  it 'is able to access the response' do
@@ -41,22 +36,22 @@ describe Grape::Middleware::Base do
41
36
 
42
37
  context 'options' do
43
38
  it 'persists options passed at initialization' do
44
- Grape::Middleware::Base.new(blank_app, {:abc => true}).options[:abc].should be_true
39
+ Grape::Middleware::Base.new(blank_app, abc: true).options[:abc].should be true
45
40
  end
46
41
 
47
42
  context 'defaults' do
48
43
  class ExampleWare < Grape::Middleware::Base
49
44
  def default_options
50
- {:monkey => true}
45
+ { monkey: true }
51
46
  end
52
47
  end
53
48
 
54
49
  it 'persists the default options' do
55
- ExampleWare.new(blank_app).options[:monkey].should be_true
50
+ ExampleWare.new(blank_app).options[:monkey].should be true
56
51
  end
57
52
 
58
53
  it 'overrides default options when provided' do
59
- ExampleWare.new(blank_app, :monkey => false).options[:monkey].should be_false
54
+ ExampleWare.new(blank_app, monkey: false).options[:monkey].should be false
60
55
  end
61
56
  end
62
57
  end