grape 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/CONTRIBUTING.md +31 -1
- data/README.md +38 -8
- data/grape.gemspec +2 -2
- data/lib/grape/api.rb +2 -2
- data/lib/grape/content_types.rb +2 -8
- data/lib/grape/dsl/desc.rb +3 -2
- data/lib/grape/dsl/inside_route.rb +6 -6
- data/lib/grape/dsl/parameters.rb +6 -1
- data/lib/grape/dsl/request_response.rb +3 -2
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +21 -19
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +4 -3
- data/lib/grape/exceptions/missing_group_type.rb +1 -6
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
- data/lib/grape/exceptions/validation_errors.rb +1 -6
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
- data/lib/grape/extensions/hash.rb +4 -7
- data/lib/grape/extensions/hashie/mash.rb +3 -3
- data/lib/grape/formatter/serializable_hash.rb +7 -7
- data/lib/grape/middleware/auth/base.rb +1 -1
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/formatter.rb +1 -1
- data/lib/grape/middleware/stack.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/request.rb +1 -1
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/types/invalid_value.rb +8 -0
- data/lib/grape/util/cache.rb +1 -1
- data/lib/grape/util/lazy_value.rb +3 -11
- data/lib/grape/util/strict_hash_configuration.rb +3 -4
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +9 -3
- data/lib/grape/validations/single_attribute_iterator.rb +3 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
- data/lib/grape/validations/types/invalid_value.rb +0 -7
- data/lib/grape/validations/validators/base.rb +9 -20
- data/lib/grape/validations/validators/default_validator.rb +2 -20
- data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
- data/lib/grape/validations/validators/values_validator.rb +14 -5
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +19 -3
- data/spec/grape/api/custom_validations_spec.rb +14 -57
- data/spec/grape/api_remount_spec.rb +36 -0
- data/spec/grape/api_spec.rb +15 -21
- data/spec/grape/dsl/desc_spec.rb +84 -85
- data/spec/grape/dsl/inside_route_spec.rb +6 -10
- data/spec/grape/dsl/request_response_spec.rb +21 -2
- data/spec/grape/endpoint_spec.rb +11 -10
- data/spec/grape/exceptions/body_parse_errors_spec.rb +40 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +3 -0
- data/spec/grape/exceptions/missing_group_type_spec.rb +5 -9
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +5 -9
- data/spec/grape/grape_spec.rb +9 -0
- data/spec/grape/integration/rack_spec.rb +6 -5
- data/spec/grape/middleware/base_spec.rb +7 -5
- data/spec/grape/middleware/formatter_spec.rb +7 -7
- data/spec/grape/request_spec.rb +4 -14
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +6 -8
- data/spec/grape/validations/single_attribute_iterator_spec.rb +8 -9
- data/spec/grape/validations/validators/base_spec.rb +38 -0
- data/spec/grape/validations/validators/values_spec.rb +56 -0
- data/spec/grape/validations_spec.rb +36 -12
- data/spec/shared/deprecated_class_examples.rb +16 -0
- metadata +112 -114
- data/lib/grape/config.rb +0 -34
- data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
- data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
- data/spec/grape/config_spec.rb +0 -17
- data/spec/grape/dsl/configuration_spec.rb +0 -14
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -4
@@ -1,48 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
context 'deprecated Grape::Validations::Base' do
|
5
|
-
subject do
|
6
|
-
Class.new(Grape::API) do
|
7
|
-
params do
|
8
|
-
requires :text, validator_with_old_base: true
|
9
|
-
end
|
10
|
-
get do
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
let(:validator_with_old_base) do
|
16
|
-
Class.new(Grape::Validations::Base) do
|
17
|
-
def validate_param!(_attr_name, _params)
|
18
|
-
true
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
before do
|
24
|
-
described_class.register_validator('validator_with_old_base', validator_with_old_base)
|
25
|
-
allow(Warning).to receive(:warn)
|
26
|
-
end
|
3
|
+
require 'shared/deprecated_class_examples'
|
27
4
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def app
|
33
|
-
subject
|
5
|
+
describe Grape::Validations do
|
6
|
+
describe 'Grape::Validations::Base' do
|
7
|
+
let(:deprecated_class) do
|
8
|
+
Class.new(Grape::Validations::Base)
|
34
9
|
end
|
35
10
|
|
36
|
-
|
37
|
-
expect(Warning).to receive(:warn) do |message|
|
38
|
-
expect(message).to include('`Grape::Validations::Base` is deprecated')
|
39
|
-
end
|
40
|
-
|
41
|
-
get '/'
|
42
|
-
end
|
11
|
+
it_behaves_like 'deprecated class'
|
43
12
|
end
|
44
13
|
|
45
|
-
|
14
|
+
describe 'using a custom length validator' do
|
46
15
|
subject do
|
47
16
|
Class.new(Grape::API) do
|
48
17
|
params do
|
@@ -64,6 +33,7 @@ describe Grape::Validations do
|
|
64
33
|
end
|
65
34
|
end
|
66
35
|
end
|
36
|
+
let(:app) { Rack::Builder.new(subject) }
|
67
37
|
|
68
38
|
before do
|
69
39
|
described_class.register_validator('default_length', default_length_validator)
|
@@ -73,10 +43,6 @@ describe Grape::Validations do
|
|
73
43
|
described_class.deregister_validator('default_length')
|
74
44
|
end
|
75
45
|
|
76
|
-
def app
|
77
|
-
subject
|
78
|
-
end
|
79
|
-
|
80
46
|
it 'under 140 characters' do
|
81
47
|
get '/', text: 'abc'
|
82
48
|
expect(last_response.status).to eq 200
|
@@ -96,7 +62,7 @@ describe Grape::Validations do
|
|
96
62
|
end
|
97
63
|
end
|
98
64
|
|
99
|
-
|
65
|
+
describe 'using a custom body-only validator' do
|
100
66
|
subject do
|
101
67
|
Class.new(Grape::API) do
|
102
68
|
params do
|
@@ -115,6 +81,7 @@ describe Grape::Validations do
|
|
115
81
|
end
|
116
82
|
end
|
117
83
|
end
|
84
|
+
let(:app) { Rack::Builder.new(subject) }
|
118
85
|
|
119
86
|
before do
|
120
87
|
described_class.register_validator('in_body', in_body_validator)
|
@@ -124,10 +91,6 @@ describe Grape::Validations do
|
|
124
91
|
described_class.deregister_validator('in_body')
|
125
92
|
end
|
126
93
|
|
127
|
-
def app
|
128
|
-
subject
|
129
|
-
end
|
130
|
-
|
131
94
|
it 'allows field in body' do
|
132
95
|
get '/', text: 'abc'
|
133
96
|
expect(last_response.status).to eq 200
|
@@ -141,7 +104,7 @@ describe Grape::Validations do
|
|
141
104
|
end
|
142
105
|
end
|
143
106
|
|
144
|
-
|
107
|
+
describe 'using a custom validator with message_key' do
|
145
108
|
subject do
|
146
109
|
Class.new(Grape::API) do
|
147
110
|
params do
|
@@ -160,6 +123,7 @@ describe Grape::Validations do
|
|
160
123
|
end
|
161
124
|
end
|
162
125
|
end
|
126
|
+
let(:app) { Rack::Builder.new(subject) }
|
163
127
|
|
164
128
|
before do
|
165
129
|
described_class.register_validator('with_message_key', message_key_validator)
|
@@ -169,10 +133,6 @@ describe Grape::Validations do
|
|
169
133
|
described_class.deregister_validator('with_message_key')
|
170
134
|
end
|
171
135
|
|
172
|
-
def app
|
173
|
-
subject
|
174
|
-
end
|
175
|
-
|
176
136
|
it 'fails with message' do
|
177
137
|
get '/', text: 'foobar'
|
178
138
|
expect(last_response.status).to eq 400
|
@@ -180,7 +140,7 @@ describe Grape::Validations do
|
|
180
140
|
end
|
181
141
|
end
|
182
142
|
|
183
|
-
|
143
|
+
describe 'using a custom request/param validator' do
|
184
144
|
subject do
|
185
145
|
Class.new(Grape::API) do
|
186
146
|
params do
|
@@ -208,6 +168,7 @@ describe Grape::Validations do
|
|
208
168
|
end
|
209
169
|
end
|
210
170
|
end
|
171
|
+
let(:app) { Rack::Builder.new(subject) }
|
211
172
|
|
212
173
|
before do
|
213
174
|
described_class.register_validator('admin', admin_validator)
|
@@ -217,10 +178,6 @@ describe Grape::Validations do
|
|
217
178
|
described_class.deregister_validator('admin')
|
218
179
|
end
|
219
180
|
|
220
|
-
def app
|
221
|
-
subject
|
222
|
-
end
|
223
|
-
|
224
181
|
it 'fail when non-admin user sets an admin field' do
|
225
182
|
get '/', admin_field: 'tester', non_admin_field: 'toaster'
|
226
183
|
expect(last_response.status).to eq 400
|
@@ -147,6 +147,42 @@ describe Grape::API do
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
+
context 'when the params are configured via a configuration' do
|
151
|
+
subject(:a_remounted_api) do
|
152
|
+
Class.new(described_class) do
|
153
|
+
params do
|
154
|
+
requires configuration[:required_attr_name], type: String
|
155
|
+
end
|
156
|
+
|
157
|
+
get(mounted { configuration[:endpoint] }) do
|
158
|
+
status 200
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when the configured param is my_attr' do
|
164
|
+
it 'requires the configured params' do
|
165
|
+
root_api.mount a_remounted_api, with: {
|
166
|
+
required_attr_name: 'my_attr',
|
167
|
+
endpoint: 'test'
|
168
|
+
}
|
169
|
+
get 'test?another_attr=1'
|
170
|
+
expect(last_response.status).to eq 400
|
171
|
+
get 'test?my_attr=1'
|
172
|
+
expect(last_response.status).to eq 200
|
173
|
+
|
174
|
+
root_api.mount a_remounted_api, with: {
|
175
|
+
required_attr_name: 'another_attr',
|
176
|
+
endpoint: 'test_b'
|
177
|
+
}
|
178
|
+
get 'test_b?another_attr=1'
|
179
|
+
expect(last_response.status).to eq 200
|
180
|
+
get 'test_b?my_attr=1'
|
181
|
+
expect(last_response.status).to eq 400
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
150
186
|
context 'when executing a standard block within a `mounted` block with all dynamic params' do
|
151
187
|
subject(:a_remounted_api) do
|
152
188
|
Class.new(described_class) do
|
data/spec/grape/api_spec.rb
CHANGED
@@ -103,22 +103,6 @@ describe Grape::API do
|
|
103
103
|
}
|
104
104
|
end
|
105
105
|
end
|
106
|
-
|
107
|
-
# Behavior as defined by rfc2616 when no header is defined
|
108
|
-
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
109
|
-
describe 'no specified accept header' do
|
110
|
-
# subject.version 'v1', using: :header
|
111
|
-
# subject.get '/hello' do
|
112
|
-
# 'hello'
|
113
|
-
# end
|
114
|
-
|
115
|
-
# it 'routes' do
|
116
|
-
# get '/hello'
|
117
|
-
# last_response.status.should eql 200
|
118
|
-
# end
|
119
|
-
end
|
120
|
-
|
121
|
-
# pending 'routes if any media type is allowed'
|
122
106
|
end
|
123
107
|
|
124
108
|
describe '.version using accept_version_header' do
|
@@ -448,9 +432,10 @@ describe Grape::API do
|
|
448
432
|
expect(last_response.body).to eql 'hiya'
|
449
433
|
end
|
450
434
|
|
435
|
+
objects = ['string', :symbol, 1, -1.1, {}, [], true, false, nil].freeze
|
451
436
|
%i[put post].each do |verb|
|
452
437
|
context verb.to_s do
|
453
|
-
|
438
|
+
objects.each do |object|
|
454
439
|
it "allows a(n) #{object.class} json object in params" do
|
455
440
|
subject.format :json
|
456
441
|
subject.send(verb) do
|
@@ -1601,7 +1586,7 @@ describe Grape::API do
|
|
1601
1586
|
|
1602
1587
|
subject.get(:hello) { 'Hello, world.' }
|
1603
1588
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('allow', 'whatever')
|
1604
|
-
expect(basic_auth_context).to
|
1589
|
+
expect(basic_auth_context).to be_a(Grape::Endpoint)
|
1605
1590
|
end
|
1606
1591
|
|
1607
1592
|
it 'has access to helper methods' do
|
@@ -3067,7 +3052,7 @@ describe Grape::API do
|
|
3067
3052
|
expect(route.description).to eq('first method')
|
3068
3053
|
expect(route.route_foo).to be_nil
|
3069
3054
|
expect(route.params).to eq({})
|
3070
|
-
expect(route.options).to
|
3055
|
+
expect(route.options).to be_a(Hash)
|
3071
3056
|
end
|
3072
3057
|
|
3073
3058
|
it 'has params which does not include format and version as named captures' do
|
@@ -3326,7 +3311,7 @@ describe Grape::API do
|
|
3326
3311
|
it 'is able to cascade' do
|
3327
3312
|
subject.mount lambda { |env|
|
3328
3313
|
headers = {}
|
3329
|
-
headers['X-Cascade'] == 'pass'
|
3314
|
+
headers['X-Cascade'] == 'pass' if env['PATH_INFO'].exclude?('boo')
|
3330
3315
|
[200, headers, ['Farfegnugen']]
|
3331
3316
|
} => '/'
|
3332
3317
|
|
@@ -3725,7 +3710,7 @@ describe Grape::API do
|
|
3725
3710
|
it 'sets the instance' do
|
3726
3711
|
expect(subject.instance).to be_nil
|
3727
3712
|
subject.compile
|
3728
|
-
expect(subject.instance).to
|
3713
|
+
expect(subject.instance).to be_a(subject.base_instance)
|
3729
3714
|
end
|
3730
3715
|
end
|
3731
3716
|
|
@@ -4241,6 +4226,15 @@ describe Grape::API do
|
|
4241
4226
|
end
|
4242
4227
|
end
|
4243
4228
|
|
4229
|
+
it 'does not override methods inherited from Class' do
|
4230
|
+
Class.define_method(:test_method) {}
|
4231
|
+
subclass = Class.new(described_class)
|
4232
|
+
expect(subclass).not_to receive(:add_setup)
|
4233
|
+
subclass.test_method
|
4234
|
+
ensure
|
4235
|
+
Class.remove_method(:test_method)
|
4236
|
+
end
|
4237
|
+
|
4244
4238
|
context 'overriding via composition' do
|
4245
4239
|
module Inherited
|
4246
4240
|
def inherited(api)
|
data/spec/grape/dsl/desc_spec.rb
CHANGED
@@ -1,99 +1,98 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
describe Grape::DSL::Desc do
|
4
|
+
subject { dummy_class }
|
5
|
+
|
6
|
+
let(:dummy_class) do
|
7
|
+
Class.new do
|
8
|
+
extend Grape::DSL::Desc
|
9
9
|
end
|
10
|
-
|
11
|
-
subject { Class.new(DescSpec::Dummy) }
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
describe '.desc' do
|
13
|
+
it 'sets a description' do
|
14
|
+
desc_text = 'The description'
|
15
|
+
options = { message: 'none' }
|
16
|
+
subject.desc desc_text, options
|
17
|
+
expect(subject.namespace_setting(:description)).to eq(options.merge(description: desc_text))
|
18
|
+
expect(subject.route_setting(:description)).to eq(options.merge(description: desc_text))
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
],
|
42
|
-
hidden: false,
|
43
|
-
deprecated: false,
|
44
|
-
is_array: true,
|
45
|
-
nickname: 'nickname',
|
46
|
-
produces: %w[array of mime_types],
|
47
|
-
consumes: %w[array of mime_types],
|
48
|
-
tags: %w[tag1 tag2],
|
49
|
-
security: %w[array of security schemes]
|
21
|
+
it 'can be set with a block' do
|
22
|
+
expected_options = {
|
23
|
+
summary: 'summary',
|
24
|
+
description: 'The description',
|
25
|
+
detail: 'more details',
|
26
|
+
params: { first: :param },
|
27
|
+
entity: Object,
|
28
|
+
default: { code: 400, message: 'Invalid' },
|
29
|
+
http_codes: [[401, 'Unauthorized', 'Entities::Error']],
|
30
|
+
named: 'My named route',
|
31
|
+
body_name: 'My body name',
|
32
|
+
headers: [
|
33
|
+
XAuthToken: {
|
34
|
+
description: 'Valdates your identity',
|
35
|
+
required: true
|
36
|
+
},
|
37
|
+
XOptionalHeader: {
|
38
|
+
description: 'Not really needed',
|
39
|
+
required: false
|
50
40
|
}
|
41
|
+
],
|
42
|
+
hidden: false,
|
43
|
+
deprecated: false,
|
44
|
+
is_array: true,
|
45
|
+
nickname: 'nickname',
|
46
|
+
produces: %w[array of mime_types],
|
47
|
+
consumes: %w[array of mime_types],
|
48
|
+
tags: %w[tag1 tag2],
|
49
|
+
security: %w[array of security schemes]
|
50
|
+
}
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
52
|
+
subject.desc 'The description' do
|
53
|
+
summary 'summary'
|
54
|
+
detail 'more details'
|
55
|
+
params(first: :param)
|
56
|
+
success Object
|
57
|
+
default code: 400, message: 'Invalid'
|
58
|
+
failure [[401, 'Unauthorized', 'Entities::Error']]
|
59
|
+
named 'My named route'
|
60
|
+
body_name 'My body name'
|
61
|
+
headers [
|
62
|
+
XAuthToken: {
|
63
|
+
description: 'Valdates your identity',
|
64
|
+
required: true
|
65
|
+
},
|
66
|
+
XOptionalHeader: {
|
67
|
+
description: 'Not really needed',
|
68
|
+
required: false
|
69
|
+
}
|
70
|
+
]
|
71
|
+
hidden false
|
72
|
+
deprecated false
|
73
|
+
is_array true
|
74
|
+
nickname 'nickname'
|
75
|
+
produces %w[array of mime_types]
|
76
|
+
consumes %w[array of mime_types]
|
77
|
+
tags %w[tag1 tag2]
|
78
|
+
security %w[array of security schemes]
|
79
|
+
end
|
79
80
|
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
expect(subject.namespace_setting(:description)).to eq(expected_options)
|
82
|
+
expect(subject.route_setting(:description)).to eq(expected_options)
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
-
|
85
|
+
it 'can be set with options and a block' do
|
86
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.')
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
93
|
-
expect(subject.namespace_setting(:description)).to eq(description: desc_text, detail: detail_text)
|
94
|
-
expect(subject.route_setting(:description)).to eq(description: desc_text, detail: detail_text)
|
95
|
-
end
|
88
|
+
desc_text = 'The description'
|
89
|
+
detail_text = 'more details'
|
90
|
+
options = { message: 'none' }
|
91
|
+
subject.desc desc_text, options do
|
92
|
+
detail detail_text
|
96
93
|
end
|
94
|
+
expect(subject.namespace_setting(:description)).to eq(description: desc_text, detail: detail_text)
|
95
|
+
expect(subject.route_setting(:description)).to eq(description: desc_text, detail: detail_text)
|
97
96
|
end
|
98
97
|
end
|
99
98
|
end
|
@@ -203,16 +203,12 @@ describe Grape::Endpoint do
|
|
203
203
|
end
|
204
204
|
|
205
205
|
describe '#file' do
|
206
|
-
before do
|
207
|
-
allow(subject).to receive(:warn)
|
208
|
-
end
|
209
|
-
|
210
206
|
describe 'set' do
|
211
207
|
context 'as file path' do
|
212
208
|
let(:file_path) { '/some/file/path' }
|
213
209
|
|
214
210
|
it 'emits a warning that this method is deprecated' do
|
215
|
-
expect(
|
211
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use sendfile or stream/)
|
216
212
|
|
217
213
|
subject.file file_path
|
218
214
|
end
|
@@ -228,7 +224,7 @@ describe Grape::Endpoint do
|
|
228
224
|
let(:file_object) { double('StreamerObject', each: nil) }
|
229
225
|
|
230
226
|
it 'emits a warning that this method is deprecated' do
|
231
|
-
expect(
|
227
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use stream to use a Stream object/)
|
232
228
|
|
233
229
|
subject.file file_object
|
234
230
|
end
|
@@ -243,7 +239,7 @@ describe Grape::Endpoint do
|
|
243
239
|
|
244
240
|
describe 'get' do
|
245
241
|
it 'emits a warning that this method is deprecated' do
|
246
|
-
expect(
|
242
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use sendfile or stream/)
|
247
243
|
|
248
244
|
subject.file
|
249
245
|
end
|
@@ -273,7 +269,7 @@ describe Grape::Endpoint do
|
|
273
269
|
end
|
274
270
|
|
275
271
|
it 'sends no deprecation warnings' do
|
276
|
-
expect(
|
272
|
+
expect(ActiveSupport::Deprecation).not_to receive(:warn)
|
277
273
|
|
278
274
|
subject.sendfile file_path
|
279
275
|
end
|
@@ -334,7 +330,7 @@ describe Grape::Endpoint do
|
|
334
330
|
end
|
335
331
|
|
336
332
|
it 'emits no deprecation warnings' do
|
337
|
-
expect(
|
333
|
+
expect(ActiveSupport::Deprecation).not_to receive(:warn)
|
338
334
|
|
339
335
|
subject.stream file_path
|
340
336
|
end
|
@@ -384,7 +380,7 @@ describe Grape::Endpoint do
|
|
384
380
|
end
|
385
381
|
|
386
382
|
it 'emits no deprecation warnings' do
|
387
|
-
expect(
|
383
|
+
expect(ActiveSupport::Deprecation).not_to receive(:warn)
|
388
384
|
|
389
385
|
subject.stream stream_object
|
390
386
|
end
|
@@ -148,13 +148,32 @@ module Grape
|
|
148
148
|
it 'sets rescue all to true' do
|
149
149
|
expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
|
150
150
|
expect(subject).to receive(:namespace_inheritable).with(:rescue_grape_exceptions, true)
|
151
|
+
expect(subject).to receive(:namespace_inheritable).with(:grape_exceptions_rescue_handler, nil)
|
151
152
|
subject.rescue_from :grape_exceptions
|
152
153
|
end
|
153
154
|
|
154
|
-
it 'sets
|
155
|
+
it 'sets given proc as rescue handler' do
|
156
|
+
rescue_handler_proc = proc {}
|
155
157
|
expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
|
156
158
|
expect(subject).to receive(:namespace_inheritable).with(:rescue_grape_exceptions, true)
|
157
|
-
subject.
|
159
|
+
expect(subject).to receive(:namespace_inheritable).with(:grape_exceptions_rescue_handler, rescue_handler_proc)
|
160
|
+
subject.rescue_from :grape_exceptions, rescue_handler_proc
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'sets given block as rescue handler' do
|
164
|
+
rescue_handler_proc = proc {}
|
165
|
+
expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
|
166
|
+
expect(subject).to receive(:namespace_inheritable).with(:rescue_grape_exceptions, true)
|
167
|
+
expect(subject).to receive(:namespace_inheritable).with(:grape_exceptions_rescue_handler, rescue_handler_proc)
|
168
|
+
subject.rescue_from :grape_exceptions, &rescue_handler_proc
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'sets a rescue handler declared through :with option' do
|
172
|
+
with_block = -> { 'hello' }
|
173
|
+
expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
|
174
|
+
expect(subject).to receive(:namespace_inheritable).with(:rescue_grape_exceptions, true)
|
175
|
+
expect(subject).to receive(:namespace_inheritable).with(:grape_exceptions_rescue_handler, an_instance_of(Proc))
|
176
|
+
subject.rescue_from :grape_exceptions, with: with_block
|
158
177
|
end
|
159
178
|
end
|
160
179
|
|
data/spec/grape/endpoint_spec.rb
CHANGED
@@ -75,7 +75,7 @@ describe Grape::Endpoint do
|
|
75
75
|
it 'sets itself in the env upon call' do
|
76
76
|
subject.get('/') { 'Hello world.' }
|
77
77
|
get '/'
|
78
|
-
expect(last_request.env['api.endpoint']).to
|
78
|
+
expect(last_request.env['api.endpoint']).to be_a(described_class)
|
79
79
|
end
|
80
80
|
|
81
81
|
describe '#status' do
|
@@ -138,7 +138,7 @@ describe Grape::Endpoint do
|
|
138
138
|
|
139
139
|
it 'includes request headers' do
|
140
140
|
get '/headers'
|
141
|
-
expect(JSON.parse(last_response.body)).to
|
141
|
+
expect(JSON.parse(last_response.body)).to include(
|
142
142
|
'Host' => 'example.org',
|
143
143
|
'Cookie' => ''
|
144
144
|
)
|
@@ -173,7 +173,7 @@ describe Grape::Endpoint do
|
|
173
173
|
|
174
174
|
get('/get/cookies')
|
175
175
|
|
176
|
-
expect(last_response.headers['Set-Cookie'].split("\n").sort).to eql [
|
176
|
+
expect(Array(last_response.headers['Set-Cookie']).flat_map { |h| h.split("\n") }.sort).to eql [
|
177
177
|
'cookie3=symbol',
|
178
178
|
'cookie4=secret+code+here',
|
179
179
|
'my-awesome-cookie1=is+cool',
|
@@ -198,8 +198,9 @@ describe Grape::Endpoint do
|
|
198
198
|
end
|
199
199
|
get('/username', {}, 'HTTP_COOKIE' => 'username=user; sandbox=false')
|
200
200
|
expect(last_response.body).to eq('user_test')
|
201
|
-
|
202
|
-
expect(
|
201
|
+
cookies = Array(last_response.headers['Set-Cookie']).flat_map { |h| h.split("\n") }
|
202
|
+
expect(cookies.first).to match(/username=user_test/)
|
203
|
+
expect(cookies.second).to match(/sandbox=true/)
|
203
204
|
end
|
204
205
|
|
205
206
|
it 'deletes cookie' do
|
@@ -213,10 +214,10 @@ describe Grape::Endpoint do
|
|
213
214
|
end
|
214
215
|
get '/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2'
|
215
216
|
expect(last_response.body).to eq('3')
|
216
|
-
cookies = last_response.headers['Set-Cookie'].split("\n").
|
217
|
+
cookies = Array(last_response.headers['Set-Cookie']).flat_map { |h| h.split("\n") }.to_h do |set_cookie|
|
217
218
|
cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
|
218
219
|
[cookie.name, cookie]
|
219
|
-
end
|
220
|
+
end
|
220
221
|
expect(cookies.size).to eq(2)
|
221
222
|
%w[and_this delete_this_cookie].each do |cookie_name|
|
222
223
|
cookie = cookies[cookie_name]
|
@@ -237,10 +238,10 @@ describe Grape::Endpoint do
|
|
237
238
|
end
|
238
239
|
get('/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2')
|
239
240
|
expect(last_response.body).to eq('3')
|
240
|
-
cookies = last_response.headers['Set-Cookie'].split("\n").
|
241
|
+
cookies = Array(last_response.headers['Set-Cookie']).flat_map { |h| h.split("\n") }.to_h do |set_cookie|
|
241
242
|
cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
|
242
243
|
[cookie.name, cookie]
|
243
|
-
end
|
244
|
+
end
|
244
245
|
expect(cookies.size).to eq(2)
|
245
246
|
%w[and_this delete_this_cookie].each do |cookie_name|
|
246
247
|
cookie = cookies[cookie_name]
|
@@ -432,7 +433,7 @@ describe Grape::Endpoint do
|
|
432
433
|
end
|
433
434
|
post '/upload', { file: '' }, 'CONTENT_TYPE' => 'multipart/form-data; boundary=foobar'
|
434
435
|
expect(last_response.status).to eq(400)
|
435
|
-
expect(last_response.body).to eq('
|
436
|
+
expect(last_response.body).to eq('file is invalid')
|
436
437
|
end
|
437
438
|
end
|
438
439
|
|