grape 0.8.0 → 0.9.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -2
- data/.rubocop_todo.yml +80 -0
- data/.travis.yml +2 -2
- data/CHANGELOG.md +21 -2
- data/Gemfile +1 -6
- data/Guardfile +1 -5
- data/README.md +110 -27
- data/Rakefile +1 -1
- data/UPGRADING.md +35 -0
- data/grape.gemspec +5 -2
- data/lib/grape.rb +20 -4
- data/lib/grape/api.rb +25 -467
- data/lib/grape/api/helpers.rb +7 -0
- data/lib/grape/dsl/callbacks.rb +27 -0
- data/lib/grape/dsl/configuration.rb +27 -0
- data/lib/grape/dsl/helpers.rb +86 -0
- data/lib/grape/dsl/inside_route.rb +227 -0
- data/lib/grape/dsl/middleware.rb +33 -0
- data/lib/grape/dsl/parameters.rb +79 -0
- data/lib/grape/dsl/request_response.rb +152 -0
- data/lib/grape/dsl/routing.rb +172 -0
- data/lib/grape/dsl/validations.rb +29 -0
- data/lib/grape/endpoint.rb +6 -226
- data/lib/grape/error_formatter/base.rb +28 -0
- data/lib/grape/error_formatter/json.rb +2 -0
- data/lib/grape/error_formatter/txt.rb +2 -0
- data/lib/grape/error_formatter/xml.rb +2 -0
- data/lib/grape/exceptions/base.rb +6 -0
- data/lib/grape/exceptions/validation.rb +3 -3
- data/lib/grape/exceptions/validation_errors.rb +19 -6
- data/lib/grape/locale/en.yml +5 -3
- data/lib/grape/middleware/auth/base.rb +28 -12
- data/lib/grape/middleware/auth/dsl.rb +35 -0
- data/lib/grape/middleware/auth/strategies.rb +24 -0
- data/lib/grape/middleware/auth/strategy_info.rb +15 -0
- data/lib/grape/validations.rb +3 -92
- data/lib/grape/validations/at_least_one_of.rb +25 -0
- data/lib/grape/validations/coerce.rb +2 -2
- data/lib/grape/validations/exactly_one_of.rb +2 -2
- data/lib/grape/validations/mutual_exclusion.rb +2 -2
- data/lib/grape/validations/presence.rb +1 -1
- data/lib/grape/validations/regexp.rb +1 -1
- data/lib/grape/validations/values.rb +1 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/helpers_spec.rb +36 -0
- data/spec/grape/api_spec.rb +72 -19
- data/spec/grape/dsl/callbacks_spec.rb +44 -0
- data/spec/grape/dsl/configuration_spec.rb +37 -0
- data/spec/grape/dsl/helpers_spec.rb +54 -0
- data/spec/grape/dsl/inside_route_spec.rb +222 -0
- data/spec/grape/dsl/middleware_spec.rb +40 -0
- data/spec/grape/dsl/parameters_spec.rb +108 -0
- data/spec/grape/dsl/request_response_spec.rb +123 -0
- data/spec/grape/dsl/routing_spec.rb +132 -0
- data/spec/grape/dsl/validations_spec.rb +55 -0
- data/spec/grape/endpoint_spec.rb +60 -11
- data/spec/grape/entity_spec.rb +9 -4
- data/spec/grape/exceptions/validation_errors_spec.rb +31 -1
- data/spec/grape/middleware/auth/base_spec.rb +34 -0
- data/spec/grape/middleware/auth/dsl_spec.rb +53 -0
- data/spec/grape/middleware/auth/strategies_spec.rb +81 -0
- data/spec/grape/middleware/error_spec.rb +33 -1
- data/spec/grape/middleware/exception_spec.rb +13 -0
- data/spec/grape/validations/at_least_one_of_spec.rb +63 -0
- data/spec/grape/validations/exactly_one_of_spec.rb +1 -1
- data/spec/grape/validations/presence_spec.rb +159 -122
- data/spec/grape/validations/zh-CN.yml +1 -1
- data/spec/grape/validations_spec.rb +77 -15
- data/spec/spec_helper.rb +1 -0
- data/spec/support/endpoint_faker.rb +23 -0
- metadata +93 -15
- data/lib/grape/middleware/auth/basic.rb +0 -13
- data/lib/grape/middleware/auth/digest.rb +0 -13
- data/lib/grape/middleware/auth/oauth2.rb +0 -83
- data/spec/grape/middleware/auth/basic_spec.rb +0 -31
- data/spec/grape/middleware/auth/digest_spec.rb +0 -47
- data/spec/grape/middleware/auth/oauth2_spec.rb +0 -135
@@ -6,12 +6,12 @@ module Grape
|
|
6
6
|
module Validations
|
7
7
|
class CoerceValidator < SingleOptionValidator
|
8
8
|
def validate_param!(attr_name, params)
|
9
|
-
raise Grape::Exceptions::Validation,
|
9
|
+
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :coerce unless params.is_a? Hash
|
10
10
|
new_value = coerce_value(@option, params[attr_name])
|
11
11
|
if valid_type?(new_value)
|
12
12
|
params[attr_name] = new_value
|
13
13
|
else
|
14
|
-
raise Grape::Exceptions::Validation,
|
14
|
+
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :coerce
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -7,7 +7,7 @@ module Grape
|
|
7
7
|
def validate!(params)
|
8
8
|
super
|
9
9
|
if none_of_restricted_params_is_present
|
10
|
-
raise Grape::Exceptions::Validation,
|
10
|
+
raise Grape::Exceptions::Validation, params: all_keys, message_key: :exactly_one
|
11
11
|
end
|
12
12
|
params
|
13
13
|
end
|
@@ -19,7 +19,7 @@ module Grape
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def all_keys
|
22
|
-
attrs.map(&:
|
22
|
+
attrs.map(&:to_s)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -6,7 +6,7 @@ module Grape
|
|
6
6
|
def validate!(params)
|
7
7
|
@params = params
|
8
8
|
if two_or_more_exclusive_params_are_present
|
9
|
-
raise Grape::Exceptions::Validation,
|
9
|
+
raise Grape::Exceptions::Validation, params: keys_in_common, message_key: :mutual_exclusion
|
10
10
|
end
|
11
11
|
params
|
12
12
|
end
|
@@ -18,7 +18,7 @@ module Grape
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def keys_in_common
|
21
|
-
attrs.map(&:to_s) & params.stringify_keys.keys
|
21
|
+
(attrs.map(&:to_s) & params.stringify_keys.keys).map(&:to_s)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -8,7 +8,7 @@ module Grape
|
|
8
8
|
|
9
9
|
def validate_param!(attr_name, params)
|
10
10
|
unless params.respond_to?(:key?) && params.key?(attr_name)
|
11
|
-
raise Grape::Exceptions::Validation,
|
11
|
+
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :presence
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -4,7 +4,7 @@ module Grape
|
|
4
4
|
def validate_param!(attr_name, params)
|
5
5
|
if params.key?(attr_name) &&
|
6
6
|
(params[attr_name].nil? || !(params[attr_name].to_s =~ @option))
|
7
|
-
raise Grape::Exceptions::Validation,
|
7
|
+
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :regexp
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -9,7 +9,7 @@ module Grape
|
|
9
9
|
|
10
10
|
def validate_param!(attr_name, params)
|
11
11
|
if (params[attr_name] || required_for_root_scope?) && !(@values.is_a?(Proc) ? @values.call : @values).include?(params[attr_name])
|
12
|
-
raise Grape::Exceptions::Validation,
|
12
|
+
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message_key: :values
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
data/lib/grape/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Grape::API::Helpers do
|
4
|
+
module SharedParams
|
5
|
+
extend Grape::API::Helpers
|
6
|
+
|
7
|
+
params :pagination do
|
8
|
+
optional :page, type: Integer
|
9
|
+
optional :size, type: Integer
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
subject do
|
14
|
+
Class.new(Grape::API) do
|
15
|
+
helpers SharedParams
|
16
|
+
format :json
|
17
|
+
|
18
|
+
params do
|
19
|
+
use :pagination
|
20
|
+
end
|
21
|
+
get do
|
22
|
+
declared(params, include_missing: true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def app
|
28
|
+
subject
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'defines parameters' do
|
32
|
+
get '/'
|
33
|
+
expect(last_response.status).to eq 200
|
34
|
+
expect(last_response.body).to eq({ page: nil, size: nil }.to_json)
|
35
|
+
end
|
36
|
+
end
|
data/spec/grape/api_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shared/versioning_examples'
|
3
|
+
require 'grape-entity'
|
3
4
|
|
4
5
|
describe Grape::API do
|
5
6
|
subject { Class.new(Grape::API) }
|
@@ -121,9 +122,11 @@ describe Grape::API do
|
|
121
122
|
|
122
123
|
describe '.namespace' do
|
123
124
|
it 'is retrievable and converted to a path' do
|
125
|
+
internal_namespace = nil
|
124
126
|
subject.namespace :awesome do
|
125
|
-
|
127
|
+
internal_namespace = namespace
|
126
128
|
end
|
129
|
+
expect(internal_namespace).to eql("/awesome")
|
127
130
|
end
|
128
131
|
|
129
132
|
it 'comes after the prefix and version' do
|
@@ -139,27 +142,31 @@ describe Grape::API do
|
|
139
142
|
end
|
140
143
|
|
141
144
|
it 'cancels itself after the block is over' do
|
145
|
+
internal_namespace = nil
|
142
146
|
subject.namespace :awesome do
|
143
|
-
|
147
|
+
internal_namespace = namespace
|
144
148
|
end
|
145
|
-
|
146
|
-
expect(subject.namespace).to eq('/')
|
149
|
+
expect(subject.namespace).to eql("/")
|
147
150
|
end
|
148
151
|
|
149
152
|
it 'is stackable' do
|
153
|
+
internal_namespace = nil
|
154
|
+
internal_second_namespace = nil
|
150
155
|
subject.namespace :awesome do
|
156
|
+
internal_namespace = namespace
|
151
157
|
namespace :rad do
|
152
|
-
|
158
|
+
internal_second_namespace = namespace
|
153
159
|
end
|
154
|
-
namespace.should == '/awesome'
|
155
160
|
end
|
156
|
-
expect(
|
161
|
+
expect(internal_namespace).to eq('/awesome')
|
162
|
+
expect(internal_second_namespace).to eq('/awesome/rad')
|
157
163
|
end
|
158
164
|
|
159
165
|
it 'accepts path segments correctly' do
|
166
|
+
inner_namespace = nil
|
160
167
|
subject.namespace :members do
|
161
168
|
namespace '/:member_id' do
|
162
|
-
|
169
|
+
inner_namespace = namespace
|
163
170
|
get '/' do
|
164
171
|
params[:member_id]
|
165
172
|
end
|
@@ -167,6 +174,7 @@ describe Grape::API do
|
|
167
174
|
end
|
168
175
|
get '/members/23'
|
169
176
|
expect(last_response.body).to eq("23")
|
177
|
+
expect(inner_namespace).to eq('/members/:member_id')
|
170
178
|
end
|
171
179
|
|
172
180
|
it 'is callable with nil just to push onto the stack' do
|
@@ -184,9 +192,11 @@ describe Grape::API do
|
|
184
192
|
|
185
193
|
%w(group resource resources segment).each do |als|
|
186
194
|
it '`.#{als}` is an alias' do
|
195
|
+
inner_namespace = nil
|
187
196
|
subject.send(als, :awesome) do
|
188
|
-
namespace
|
197
|
+
inner_namespace = namespace
|
189
198
|
end
|
199
|
+
expect(inner_namespace).to eq "/awesome"
|
190
200
|
end
|
191
201
|
end
|
192
202
|
end
|
@@ -320,8 +330,11 @@ describe Grape::API do
|
|
320
330
|
|
321
331
|
context 'format' do
|
322
332
|
before(:each) do
|
333
|
+
allow_any_instance_of(Object).to receive(:to_json).and_return("abc")
|
334
|
+
allow_any_instance_of(Object).to receive(:to_txt).and_return("def")
|
335
|
+
|
323
336
|
subject.get("/abc") do
|
324
|
-
|
337
|
+
Object.new
|
325
338
|
end
|
326
339
|
end
|
327
340
|
|
@@ -792,11 +805,11 @@ describe Grape::API do
|
|
792
805
|
it "uploads and downloads a PNG file via #{url}" do
|
793
806
|
image_filename = "grape.png"
|
794
807
|
post url, file: Rack::Test::UploadedFile.new(image_filename, 'image/png', true)
|
795
|
-
last_response.status.
|
796
|
-
last_response.headers['Content-Type'].
|
797
|
-
last_response.headers['Content-Disposition'].
|
808
|
+
expect(last_response.status).to eq(201)
|
809
|
+
expect(last_response.headers['Content-Type']).to eq("image/png")
|
810
|
+
expect(last_response.headers['Content-Disposition']).to eq("attachment; filename*=UTF-8''grape.png")
|
798
811
|
File.open(image_filename, 'rb') do |io|
|
799
|
-
last_response.body.
|
812
|
+
expect(last_response.body).to eq io.read
|
800
813
|
end
|
801
814
|
end
|
802
815
|
end
|
@@ -804,11 +817,11 @@ describe Grape::API do
|
|
804
817
|
it "uploads and downloads a Ruby file" do
|
805
818
|
filename = __FILE__
|
806
819
|
post "/attachment.rb", file: Rack::Test::UploadedFile.new(filename, 'application/x-ruby', true)
|
807
|
-
last_response.status.
|
808
|
-
last_response.headers['Content-Type'].
|
809
|
-
last_response.headers['Content-Disposition'].
|
820
|
+
expect(last_response.status).to eq(201)
|
821
|
+
expect(last_response.headers['Content-Type']).to eq("application/x-ruby")
|
822
|
+
expect(last_response.headers['Content-Disposition']).to eq("attachment; filename*=UTF-8''api_spec.rb")
|
810
823
|
File.open(filename, 'rb') do |io|
|
811
|
-
last_response.body.
|
824
|
+
expect(last_response.body).to eq io.read
|
812
825
|
end
|
813
826
|
end
|
814
827
|
end
|
@@ -864,13 +877,15 @@ describe Grape::API do
|
|
864
877
|
end
|
865
878
|
|
866
879
|
it 'does not show up outside the namespace' do
|
880
|
+
inner_middleware = nil
|
867
881
|
subject.use ApiSpec::PhonyMiddleware, 123
|
868
882
|
subject.namespace :awesome do
|
869
883
|
use ApiSpec::PhonyMiddleware, 'abc'
|
870
|
-
|
884
|
+
inner_middleware = middleware
|
871
885
|
end
|
872
886
|
|
873
887
|
expect(subject.middleware).to eql [[ApiSpec::PhonyMiddleware, 123]]
|
888
|
+
expect(inner_middleware).to eql [[ApiSpec::PhonyMiddleware, 123], [ApiSpec::PhonyMiddleware, 'abc']]
|
874
889
|
end
|
875
890
|
|
876
891
|
it 'calls the middleware' do
|
@@ -1748,6 +1763,44 @@ describe Grape::API do
|
|
1748
1763
|
end
|
1749
1764
|
end
|
1750
1765
|
|
1766
|
+
context 'http_codes' do
|
1767
|
+
let(:error_presenter) do
|
1768
|
+
Class.new(Grape::Entity) do
|
1769
|
+
expose :code
|
1770
|
+
expose :static
|
1771
|
+
|
1772
|
+
def static
|
1773
|
+
'some static text'
|
1774
|
+
end
|
1775
|
+
end
|
1776
|
+
end
|
1777
|
+
|
1778
|
+
it 'is used as presenter' do
|
1779
|
+
subject.desc 'some desc', http_codes: [
|
1780
|
+
[408, 'Unauthorized', error_presenter]
|
1781
|
+
]
|
1782
|
+
|
1783
|
+
subject.get '/exception' do
|
1784
|
+
error!({ code: 408 }, 408)
|
1785
|
+
end
|
1786
|
+
|
1787
|
+
get '/exception'
|
1788
|
+
expect(last_response.status).to eql 408
|
1789
|
+
expect(last_response.body).to eql({ code: 408, static: 'some static text' }.to_json)
|
1790
|
+
end
|
1791
|
+
|
1792
|
+
it 'presented with' do
|
1793
|
+
error = { code: 408, with: error_presenter }
|
1794
|
+
subject.get '/exception' do
|
1795
|
+
error! error, 408
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
get '/exception'
|
1799
|
+
expect(last_response.status).to eql 408
|
1800
|
+
expect(last_response.body).to eql({ code: 408, static: 'some static text' }.to_json)
|
1801
|
+
end
|
1802
|
+
end
|
1803
|
+
|
1751
1804
|
context 'routes' do
|
1752
1805
|
describe 'empty api structure' do
|
1753
1806
|
it 'returns an empty array of routes' do
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module DSL
|
5
|
+
module CallbacksSpec
|
6
|
+
class Dummy
|
7
|
+
include Grape::DSL::Callbacks
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Callbacks do
|
12
|
+
subject { Class.new(CallbacksSpec::Dummy) }
|
13
|
+
let(:proc) { ->() {} }
|
14
|
+
|
15
|
+
describe '.before' do
|
16
|
+
it 'adds a block to "before"' do
|
17
|
+
expect(subject).to receive(:imbue).with(:befores, [proc])
|
18
|
+
subject.before(&proc)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.before_validation' do
|
23
|
+
it 'adds a block to "before_validation"' do
|
24
|
+
expect(subject).to receive(:imbue).with(:before_validations, [proc])
|
25
|
+
subject.before_validation(&proc)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.after_validation' do
|
30
|
+
it 'adds a block to "after_validation"' do
|
31
|
+
expect(subject).to receive(:imbue).with(:after_validations, [proc])
|
32
|
+
subject.after_validation(&proc)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.after' do
|
37
|
+
it 'adds a block to "after"' do
|
38
|
+
expect(subject).to receive(:imbue).with(:afters, [proc])
|
39
|
+
subject.after(&proc)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module DSL
|
5
|
+
module ConfigurationSpec
|
6
|
+
class Dummy
|
7
|
+
include Grape::DSL::Configuration
|
8
|
+
|
9
|
+
# rubocop:disable TrivialAccessors
|
10
|
+
def self.last_desc
|
11
|
+
@last_description
|
12
|
+
end
|
13
|
+
# rubocop:enable TrivialAccessors
|
14
|
+
end
|
15
|
+
end
|
16
|
+
describe Configuration do
|
17
|
+
subject { Class.new(ConfigurationSpec::Dummy) }
|
18
|
+
let(:logger) { double(:logger) }
|
19
|
+
|
20
|
+
describe '.logger' do
|
21
|
+
it 'sets a logger' do
|
22
|
+
subject.logger logger
|
23
|
+
expect(subject.logger).to eq logger
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.desc' do
|
28
|
+
it 'sets a description' do
|
29
|
+
options = { message: 'none' }
|
30
|
+
subject.desc options
|
31
|
+
expect(subject.last_desc).to eq(description: options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module DSL
|
5
|
+
module HelpersSpec
|
6
|
+
class Dummy
|
7
|
+
include Grape::DSL::Helpers
|
8
|
+
|
9
|
+
def self.settings
|
10
|
+
@settings ||= Grape::Util::HashStack.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.set(_, mod)
|
14
|
+
@mod = mod
|
15
|
+
end
|
16
|
+
|
17
|
+
# rubocop:disable TrivialAccessors
|
18
|
+
def self.mod
|
19
|
+
@mod
|
20
|
+
end
|
21
|
+
# rubocop:enable TrivialAccessors
|
22
|
+
end
|
23
|
+
end
|
24
|
+
describe Helpers do
|
25
|
+
subject { Class.new(HelpersSpec::Dummy) }
|
26
|
+
let(:proc) do
|
27
|
+
->(*) do
|
28
|
+
def test
|
29
|
+
:test
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.helpers' do
|
35
|
+
it 'adds a module with the given block' do
|
36
|
+
expect(subject).to receive(:set).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original
|
37
|
+
subject.helpers(&proc)
|
38
|
+
|
39
|
+
expect(subject.mod.instance_methods).to include(:test)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'uses provided modules' do
|
43
|
+
mod = Module.new
|
44
|
+
|
45
|
+
expect(subject).to receive(:set).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original
|
46
|
+
subject.helpers(mod, &proc)
|
47
|
+
|
48
|
+
expect(subject.mod).not_to eq mod
|
49
|
+
expect(subject.mod).to include mod
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
module DSL
|
5
|
+
module InsideRouteSpec
|
6
|
+
class Dummy
|
7
|
+
include Grape::DSL::InsideRoute
|
8
|
+
|
9
|
+
attr_reader :env, :request, :settings
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@env = {}
|
13
|
+
@header = {}
|
14
|
+
@settings = Grape::Util::HashStack.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Endpoint do
|
20
|
+
subject { InsideRouteSpec::Dummy.new }
|
21
|
+
|
22
|
+
describe '#version' do
|
23
|
+
it 'defaults to nil' do
|
24
|
+
expect(subject.version).to be nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns env[api.version]' do
|
28
|
+
subject.env['api.version'] = 'dummy'
|
29
|
+
expect(subject.version).to eq 'dummy'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#error!' do
|
34
|
+
it 'throws :error' do
|
35
|
+
expect { subject.error! 'Not Found', 404 }.to throw_symbol(:error)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'thrown' do
|
39
|
+
before do
|
40
|
+
catch(:error) { subject.error! 'Not Found', 404 }
|
41
|
+
end
|
42
|
+
it 'sets status' do
|
43
|
+
expect(subject.status).to eq 404
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'default_error_status' do
|
48
|
+
before do
|
49
|
+
subject.settings[:default_error_status] = 500
|
50
|
+
catch(:error) { subject.error! 'Unknown' }
|
51
|
+
end
|
52
|
+
it 'sets status to default_error_status' do
|
53
|
+
expect(subject.status).to eq 500
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# self.status(status || settings[:default_error_status])
|
58
|
+
# throw :error, message: message, status: self.status, headers: headers
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#redirect' do
|
62
|
+
describe 'default' do
|
63
|
+
before do
|
64
|
+
subject.redirect '/'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'sets status to 302' do
|
68
|
+
expect(subject.status).to eq 302
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'sets location header' do
|
72
|
+
expect(subject.header['Location']).to eq '/'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'permanent' do
|
77
|
+
before do
|
78
|
+
subject.redirect '/', permanent: true
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'sets status to 301' do
|
82
|
+
expect(subject.status).to eq 301
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'sets location header' do
|
86
|
+
expect(subject.header['Location']).to eq '/'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#status' do
|
92
|
+
['GET', 'PUT', 'DELETE', 'OPTIONS'].each do |method|
|
93
|
+
it 'defaults to 200 on GET' do
|
94
|
+
request = Grape::Request.new(Rack::MockRequest.env_for('/', method: method))
|
95
|
+
expect(subject).to receive(:request).and_return(request)
|
96
|
+
expect(subject.status).to eq 200
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'defaults to 201 on POST' do
|
101
|
+
request = Grape::Request.new(Rack::MockRequest.env_for('/', method: 'POST'))
|
102
|
+
expect(subject).to receive(:request).and_return(request)
|
103
|
+
expect(subject.status).to eq 201
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'returns status set' do
|
107
|
+
subject.status 501
|
108
|
+
expect(subject.status).to eq 501
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#header' do
|
113
|
+
describe 'set' do
|
114
|
+
before do
|
115
|
+
subject.header 'Name', 'Value'
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'returns value' do
|
119
|
+
expect(subject.header['Name']).to eq 'Value'
|
120
|
+
expect(subject.header('Name')).to eq 'Value'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'returns nil' do
|
125
|
+
expect(subject.header['Name']).to be nil
|
126
|
+
expect(subject.header('Name')).to be nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#content_type' do
|
131
|
+
describe 'set' do
|
132
|
+
before do
|
133
|
+
subject.content_type 'text/plain'
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'returns value' do
|
137
|
+
expect(subject.content_type).to eq 'text/plain'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'returns default' do
|
142
|
+
expect(subject.content_type).to be nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#cookies' do
|
147
|
+
it 'returns an instance of Cookies' do
|
148
|
+
expect(subject.cookies).to be_a Grape::Cookies
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe '#body' do
|
153
|
+
describe 'set' do
|
154
|
+
before do
|
155
|
+
subject.body 'body'
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns value' do
|
159
|
+
expect(subject.body).to eq 'body'
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'returns default' do
|
164
|
+
expect(subject.body).to be nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '#route' do
|
169
|
+
before do
|
170
|
+
subject.env['rack.routing_args'] = {}
|
171
|
+
subject.env['rack.routing_args'][:route_info] = 'dummy'
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns route_info' do
|
175
|
+
expect(subject.route).to eq 'dummy'
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe '#present' do
|
180
|
+
# see entity_spec.rb for entity representation spec coverage
|
181
|
+
|
182
|
+
describe 'dummy' do
|
183
|
+
before do
|
184
|
+
subject.present 'dummy'
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'presents dummy object' do
|
188
|
+
expect(subject.body).to eq 'dummy'
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe 'with' do
|
193
|
+
describe 'entity' do
|
194
|
+
let(:entity_mock) do
|
195
|
+
entity_mock = Object.new
|
196
|
+
allow(entity_mock).to receive(:represent).and_return('dummy')
|
197
|
+
entity_mock
|
198
|
+
end
|
199
|
+
|
200
|
+
describe 'instance' do
|
201
|
+
before do
|
202
|
+
subject.present 'dummy', with: entity_mock
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'presents dummy object' do
|
206
|
+
expect(subject.body).to eq 'dummy'
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#declared' do
|
214
|
+
# see endpoint_spec.rb#declared for spec coverage
|
215
|
+
|
216
|
+
it 'returns an empty hash' do
|
217
|
+
expect(subject.declared({})).to eq({})
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|