grape 1.7.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +30 -25
  5. data/UPGRADING.md +35 -0
  6. data/grape.gemspec +3 -6
  7. data/lib/grape/api.rb +2 -2
  8. data/lib/grape/content_types.rb +2 -8
  9. data/lib/grape/dsl/desc.rb +1 -1
  10. data/lib/grape/dsl/inside_route.rb +11 -11
  11. data/lib/grape/dsl/request_response.rb +2 -1
  12. data/lib/grape/dsl/settings.rb +2 -6
  13. data/lib/grape/endpoint.rb +28 -18
  14. data/lib/grape/error_formatter/base.rb +1 -1
  15. data/lib/grape/exceptions/base.rb +2 -2
  16. data/lib/grape/exceptions/missing_group_type.rb +1 -6
  17. data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
  18. data/lib/grape/exceptions/validation_errors.rb +1 -6
  19. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
  20. data/lib/grape/extensions/hash.rb +4 -7
  21. data/lib/grape/extensions/hashie/mash.rb +3 -3
  22. data/lib/grape/formatter/serializable_hash.rb +7 -7
  23. data/lib/grape/http/headers.rb +12 -2
  24. data/lib/grape/middleware/auth/base.rb +1 -1
  25. data/lib/grape/middleware/auth/strategies.rb +1 -2
  26. data/lib/grape/middleware/error.rb +5 -5
  27. data/lib/grape/middleware/formatter.rb +6 -6
  28. data/lib/grape/middleware/versioner/header.rb +11 -19
  29. data/lib/grape/railtie.rb +9 -0
  30. data/lib/grape/request.rb +8 -2
  31. data/lib/grape/router/route.rb +1 -3
  32. data/lib/grape/util/lazy_value.rb +3 -11
  33. data/lib/grape/util/strict_hash_configuration.rb +3 -4
  34. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  35. data/lib/grape/validations/params_scope.rb +8 -2
  36. data/lib/grape/validations/single_attribute_iterator.rb +3 -1
  37. data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
  38. data/lib/grape/validations/validators/base.rb +9 -20
  39. data/lib/grape/validations/validators/default_validator.rb +2 -20
  40. data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
  41. data/lib/grape/validations/validators/values_validator.rb +14 -5
  42. data/lib/grape/version.rb +1 -1
  43. data/lib/grape.rb +26 -5
  44. metadata +13 -253
  45. data/lib/grape/config.rb +0 -34
  46. data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
  47. data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
  48. data/spec/grape/api/custom_validations_spec.rb +0 -256
  49. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  50. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  51. data/spec/grape/api/documentation_spec.rb +0 -59
  52. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  53. data/spec/grape/api/instance_spec.rb +0 -103
  54. data/spec/grape/api/invalid_format_spec.rb +0 -45
  55. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  56. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  57. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  58. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  59. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  60. data/spec/grape/api/recognize_path_spec.rb +0 -21
  61. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  62. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  63. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  64. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  65. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  66. data/spec/grape/api_remount_spec.rb +0 -473
  67. data/spec/grape/api_spec.rb +0 -4347
  68. data/spec/grape/config_spec.rb +0 -17
  69. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  70. data/spec/grape/dsl/desc_spec.rb +0 -101
  71. data/spec/grape/dsl/headers_spec.rb +0 -62
  72. data/spec/grape/dsl/helpers_spec.rb +0 -100
  73. data/spec/grape/dsl/inside_route_spec.rb +0 -535
  74. data/spec/grape/dsl/logger_spec.rb +0 -24
  75. data/spec/grape/dsl/middleware_spec.rb +0 -60
  76. data/spec/grape/dsl/parameters_spec.rb +0 -180
  77. data/spec/grape/dsl/request_response_spec.rb +0 -206
  78. data/spec/grape/dsl/routing_spec.rb +0 -275
  79. data/spec/grape/dsl/settings_spec.rb +0 -261
  80. data/spec/grape/dsl/validations_spec.rb +0 -55
  81. data/spec/grape/endpoint/declared_spec.rb +0 -846
  82. data/spec/grape/endpoint_spec.rb +0 -1085
  83. data/spec/grape/entity_spec.rb +0 -336
  84. data/spec/grape/exceptions/base_spec.rb +0 -81
  85. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -145
  86. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  87. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  88. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  89. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  90. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -21
  91. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  92. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  93. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  94. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  95. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -23
  96. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  97. data/spec/grape/exceptions/validation_spec.rb +0 -19
  98. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  99. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  100. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  101. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  102. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  103. data/spec/grape/integration/rack_spec.rb +0 -51
  104. data/spec/grape/loading_spec.rb +0 -44
  105. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  106. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  107. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  108. data/spec/grape/middleware/base_spec.rb +0 -221
  109. data/spec/grape/middleware/error_spec.rb +0 -85
  110. data/spec/grape/middleware/exception_spec.rb +0 -294
  111. data/spec/grape/middleware/formatter_spec.rb +0 -461
  112. data/spec/grape/middleware/globals_spec.rb +0 -30
  113. data/spec/grape/middleware/stack_spec.rb +0 -155
  114. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  115. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  116. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  117. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  118. data/spec/grape/middleware/versioner_spec.rb +0 -21
  119. data/spec/grape/named_api_spec.rb +0 -19
  120. data/spec/grape/parser_spec.rb +0 -86
  121. data/spec/grape/path_spec.rb +0 -252
  122. data/spec/grape/presenters/presenter_spec.rb +0 -71
  123. data/spec/grape/request_spec.rb +0 -136
  124. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  125. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  126. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  127. data/spec/grape/util/stackable_values_spec.rb +0 -128
  128. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  129. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  130. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  131. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -40
  132. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  133. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -57
  134. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  135. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  136. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  137. data/spec/grape/validations/types_spec.rb +0 -111
  138. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  139. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  140. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  141. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  142. data/spec/grape/validations/validators/default_spec.rb +0 -463
  143. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  144. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  145. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  146. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  147. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  148. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  149. data/spec/grape/validations/validators/values_spec.rb +0 -696
  150. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  151. data/spec/grape/validations_spec.rb +0 -2029
  152. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  153. data/spec/integration/multi_json/json_spec.rb +0 -7
  154. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  155. data/spec/shared/versioning_examples.rb +0 -215
  156. data/spec/spec_helper.rb +0 -52
  157. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  158. data/spec/support/chunks.rb +0 -14
  159. data/spec/support/content_type_helpers.rb +0 -15
  160. data/spec/support/endpoint_faker.rb +0 -25
  161. data/spec/support/file_streamer.rb +0 -13
  162. data/spec/support/integer_helpers.rb +0 -13
  163. data/spec/support/versioned_helpers.rb +0 -55
@@ -1,221 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Grape::Middleware::Base do
4
- subject { described_class.new(blank_app) }
5
-
6
- let(:blank_app) { ->(_) { [200, {}, 'Hi there.'] } }
7
-
8
- before do
9
- # Keep it one object for testing.
10
- allow(subject).to receive(:dup).and_return(subject)
11
- end
12
-
13
- it 'has the app as an accessor' do
14
- expect(subject.app).to eq(blank_app)
15
- end
16
-
17
- it 'calls through to the app' do
18
- expect(subject.call({})).to eq([200, {}, 'Hi there.'])
19
- end
20
-
21
- context 'callbacks' do
22
- after { subject.call!({}) }
23
-
24
- it 'calls #before' do
25
- expect(subject).to receive(:before)
26
- end
27
-
28
- it 'calls #after' do
29
- expect(subject).to receive(:after)
30
- end
31
- end
32
-
33
- context 'callbacks on error' do
34
- let(:blank_app) { ->(_) { raise StandardError } }
35
-
36
- it 'calls #after' do
37
- expect(subject).to receive(:after)
38
- expect { subject.call({}) }.to raise_error(StandardError)
39
- end
40
- end
41
-
42
- context 'after callback' do
43
- before do
44
- allow(subject).to receive(:after).and_return([200, {}, 'Hello from after callback'])
45
- end
46
-
47
- it 'overwrites application response' do
48
- expect(subject.call!({}).last).to eq('Hello from after callback')
49
- end
50
- end
51
-
52
- context 'after callback with errors' do
53
- it 'does not overwrite the application response' do
54
- expect(subject.call({})).to eq([200, {}, 'Hi there.'])
55
- end
56
-
57
- context 'with patched warnings' do
58
- before do
59
- @warnings = warnings = []
60
- allow_any_instance_of(described_class).to receive(:warn) { |m| warnings << m }
61
- allow(subject).to receive(:after).and_raise(StandardError)
62
- end
63
-
64
- it 'does show a warning' do
65
- expect { subject.call({}) }.to raise_error(StandardError)
66
- expect(@warnings).not_to be_empty
67
- end
68
- end
69
- end
70
-
71
- it 'is able to access the response' do
72
- subject.call({})
73
- expect(subject.response).to be_a(Rack::Response)
74
- end
75
-
76
- describe '#response' do
77
- subject do
78
- described_class.new(response)
79
- end
80
-
81
- before { subject.call({}) }
82
-
83
- context 'when Array' do
84
- let(:rack_response) { Rack::Response.new('test', 204, abc: 1) }
85
- let(:response) { ->(_) { [204, { abc: 1 }, 'test'] } }
86
-
87
- it 'status' do
88
- expect(subject.response.status).to eq(204)
89
- end
90
-
91
- it 'body' do
92
- expect(subject.response.body).to eq(['test'])
93
- end
94
-
95
- it 'header' do
96
- expect(subject.response.header).to have_key(:abc)
97
- end
98
-
99
- it 'returns the memoized Rack::Response instance' do
100
- allow(Rack::Response).to receive(:new).and_return(rack_response)
101
- expect(subject.response).to eq(rack_response)
102
- end
103
- end
104
-
105
- context 'when Rack::Response' do
106
- let(:rack_response) { Rack::Response.new('test', 204, abc: 1) }
107
- let(:response) { ->(_) { rack_response } }
108
-
109
- it 'status' do
110
- expect(subject.response.status).to eq(204)
111
- end
112
-
113
- it 'body' do
114
- expect(subject.response.body).to eq(['test'])
115
- end
116
-
117
- it 'header' do
118
- expect(subject.response.header).to have_key(:abc)
119
- end
120
-
121
- it 'returns the memoized Rack::Response instance' do
122
- expect(subject.response).to eq(rack_response)
123
- end
124
- end
125
- end
126
-
127
- describe '#context' do
128
- subject { described_class.new(blank_app) }
129
-
130
- it 'allows access to response context' do
131
- subject.call(Grape::Env::API_ENDPOINT => { header: 'some header' })
132
- expect(subject.context).to eq(header: 'some header')
133
- end
134
- end
135
-
136
- context 'options' do
137
- it 'persists options passed at initialization' do
138
- expect(described_class.new(blank_app, abc: true).options[:abc]).to be true
139
- end
140
-
141
- context 'defaults' do
142
- module BaseSpec
143
- class ExampleWare < Grape::Middleware::Base
144
- def default_options
145
- { monkey: true }
146
- end
147
- end
148
- end
149
-
150
- it 'persists the default options' do
151
- expect(BaseSpec::ExampleWare.new(blank_app).options[:monkey]).to be true
152
- end
153
-
154
- it 'overrides default options when provided' do
155
- expect(BaseSpec::ExampleWare.new(blank_app, monkey: false).options[:monkey]).to be false
156
- end
157
- end
158
- end
159
-
160
- context 'header' do
161
- module HeaderSpec
162
- class ExampleWare < Grape::Middleware::Base
163
- def before
164
- header 'X-Test-Before', 'Hi'
165
- end
166
-
167
- def after
168
- header 'X-Test-After', 'Bye'
169
- nil
170
- end
171
- end
172
- end
173
-
174
- def app
175
- Rack::Builder.app do
176
- use HeaderSpec::ExampleWare
177
- run ->(_) { [200, {}, ['Yeah']] }
178
- end
179
- end
180
-
181
- it 'is able to set a header' do
182
- get '/'
183
- expect(last_response.headers['X-Test-Before']).to eq('Hi')
184
- expect(last_response.headers['X-Test-After']).to eq('Bye')
185
- end
186
- end
187
-
188
- context 'header overwrite' do
189
- module HeaderOverwritingSpec
190
- class ExampleWare < Grape::Middleware::Base
191
- def before
192
- header 'X-Test-Overwriting', 'Hi'
193
- end
194
-
195
- def after
196
- header 'X-Test-Overwriting', 'Bye'
197
- nil
198
- end
199
- end
200
-
201
- class API < Grape::API
202
- get('/') do
203
- header 'X-Test-Overwriting', 'Yeah'
204
- 'Hello'
205
- end
206
- end
207
- end
208
-
209
- def app
210
- Rack::Builder.app do
211
- use HeaderOverwritingSpec::ExampleWare
212
- run HeaderOverwritingSpec::API.new
213
- end
214
- end
215
-
216
- it 'overwrites header by after headers' do
217
- get '/'
218
- expect(last_response.headers['X-Test-Overwriting']).to eq('Bye')
219
- end
220
- end
221
- end
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'grape-entity'
4
-
5
- describe Grape::Middleware::Error do
6
- module ErrorSpec
7
- class ErrorEntity < Grape::Entity
8
- expose :code
9
- expose :static
10
-
11
- def static
12
- 'static text'
13
- end
14
- end
15
-
16
- class ErrApp
17
- class << self
18
- attr_accessor :error, :format
19
-
20
- def call(_env)
21
- throw :error, error
22
- end
23
- end
24
- end
25
- end
26
-
27
- def app
28
- opts = options
29
- Rack::Builder.app do
30
- use Spec::Support::EndpointFaker
31
- use Grape::Middleware::Error, **opts
32
- run ErrorSpec::ErrApp
33
- end
34
- end
35
-
36
- let(:options) { { default_message: 'Aww, hamburgers.' } }
37
-
38
- it 'sets the status code appropriately' do
39
- ErrorSpec::ErrApp.error = { status: 410 }
40
- get '/'
41
- expect(last_response.status).to eq(410)
42
- end
43
-
44
- it 'sets the status code based on the rack util status code symbol' do
45
- ErrorSpec::ErrApp.error = { status: :gone }
46
- get '/'
47
- expect(last_response.status).to eq(410)
48
- end
49
-
50
- it 'sets the error message appropriately' do
51
- ErrorSpec::ErrApp.error = { message: 'Awesome stuff.' }
52
- get '/'
53
- expect(last_response.body).to eq('Awesome stuff.')
54
- end
55
-
56
- it 'defaults to a 500 status' do
57
- ErrorSpec::ErrApp.error = {}
58
- get '/'
59
- expect(last_response.status).to eq(500)
60
- end
61
-
62
- it 'has a default message' do
63
- ErrorSpec::ErrApp.error = {}
64
- get '/'
65
- expect(last_response.body).to eq('Aww, hamburgers.')
66
- end
67
-
68
- context 'with http code' do
69
- let(:options) { { default_message: 'Aww, hamburgers.' } }
70
-
71
- it 'adds the status code if wanted' do
72
- ErrorSpec::ErrApp.error = { message: { code: 200 } }
73
- get '/'
74
-
75
- expect(last_response.body).to eq({ code: 200 }.to_json)
76
- end
77
-
78
- it 'presents an error message' do
79
- ErrorSpec::ErrApp.error = { message: { code: 200, with: ErrorSpec::ErrorEntity } }
80
- get '/'
81
-
82
- expect(last_response.body).to eq({ code: 200, static: 'static text' }.to_json)
83
- end
84
- end
85
- end
@@ -1,294 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Grape::Middleware::Error do
4
- let(:exception_app) do
5
- Class.new do
6
- class << self
7
- def call(_env)
8
- raise 'rain!'
9
- end
10
- end
11
- end
12
- end
13
-
14
- let(:other_exception_app) do
15
- Class.new do
16
- class << self
17
- def call(_env)
18
- raise NotImplementedError, 'snow!'
19
- end
20
- end
21
- end
22
- end
23
-
24
- let(:custom_error_app) do
25
- Class.new do
26
- class << self
27
- class CustomError < Grape::Exceptions::Base; end
28
-
29
- def call(_env)
30
- raise CustomError.new(status: 400, message: 'failed validation')
31
- end
32
- end
33
- end
34
- end
35
-
36
- let(:error_hash_app) do
37
- Class.new do
38
- class << self
39
- def error!(message, status)
40
- throw :error, message: { error: message, detail: 'missing widget' }, status: status
41
- end
42
-
43
- def call(_env)
44
- error!('rain!', 401)
45
- end
46
- end
47
- end
48
- end
49
-
50
- let(:access_denied_app) do
51
- Class.new do
52
- class << self
53
- def error!(message, status)
54
- throw :error, message: message, status: status
55
- end
56
-
57
- def call(_env)
58
- error!('Access Denied', 401)
59
- end
60
- end
61
- end
62
- end
63
-
64
- let(:app) do
65
- builder = Rack::Builder.new
66
- builder.use Spec::Support::EndpointFaker
67
- if options.any?
68
- builder.use described_class, options
69
- else
70
- builder.use described_class
71
- end
72
- builder.run running_app
73
- builder.to_app
74
- end
75
-
76
- context 'with defaults' do
77
- let(:running_app) { exception_app }
78
- let(:options) { {} }
79
-
80
- it 'does not trap errors by default' do
81
- expect { get '/' }.to raise_error(RuntimeError, 'rain!')
82
- end
83
- end
84
-
85
- context 'with rescue_all' do
86
- context 'StandardError exception' do
87
- let(:running_app) { exception_app }
88
- let(:options) { { rescue_all: true } }
89
-
90
- it 'sets the message appropriately' do
91
- get '/'
92
- expect(last_response.body).to eq('rain!')
93
- end
94
-
95
- it 'defaults to a 500 status' do
96
- get '/'
97
- expect(last_response.status).to eq(500)
98
- end
99
- end
100
-
101
- context 'Non-StandardError exception' do
102
- let(:running_app) { other_exception_app }
103
- let(:options) { { rescue_all: true } }
104
-
105
- it 'does not trap errors other than StandardError' do
106
- expect { get '/' }.to raise_error(NotImplementedError, 'snow!')
107
- end
108
- end
109
- end
110
-
111
- context 'Non-StandardError exception with a provided rescue handler' do
112
- context 'default error response' do
113
- let(:running_app) { other_exception_app }
114
- let(:options) { { rescue_handlers: { NotImplementedError => nil } } }
115
-
116
- it 'rescues the exception using the default handler' do
117
- get '/'
118
- expect(last_response.body).to eq('snow!')
119
- end
120
- end
121
-
122
- context 'custom error response' do
123
- let(:running_app) { other_exception_app }
124
- let(:options) { { rescue_handlers: { NotImplementedError => -> { Rack::Response.new('rescued', 200, {}) } } } }
125
-
126
- it 'rescues the exception using the provided handler' do
127
- get '/'
128
- expect(last_response.body).to eq('rescued')
129
- end
130
- end
131
- end
132
-
133
- context do
134
- let(:running_app) { exception_app }
135
- let(:options) { { rescue_all: true, default_status: 500 } }
136
-
137
- it 'is possible to specify a different default status code' do
138
- get '/'
139
- expect(last_response.status).to eq(500)
140
- end
141
- end
142
-
143
- context do
144
- let(:running_app) { exception_app }
145
- let(:options) { { rescue_all: true, format: :json } }
146
-
147
- it 'is possible to return errors in json format' do
148
- get '/'
149
- expect(last_response.body).to eq('{"error":"rain!"}')
150
- end
151
- end
152
-
153
- context do
154
- let(:running_app) { error_hash_app }
155
- let(:options) { { rescue_all: true, format: :json } }
156
-
157
- it 'is possible to return hash errors in json format' do
158
- get '/'
159
- expect(['{"error":"rain!","detail":"missing widget"}',
160
- '{"detail":"missing widget","error":"rain!"}']).to include(last_response.body)
161
- end
162
- end
163
-
164
- context do
165
- let(:running_app) { exception_app }
166
- let(:options) { { rescue_all: true, format: :jsonapi } }
167
-
168
- it 'is possible to return errors in jsonapi format' do
169
- get '/'
170
- expect(last_response.body).to eq('{&quot;error&quot;:&quot;rain!&quot;}')
171
- end
172
- end
173
-
174
- context do
175
- let(:running_app) { error_hash_app }
176
- let(:options) { { rescue_all: true, format: :jsonapi } }
177
-
178
- it 'is possible to return hash errors in jsonapi format' do
179
- get '/'
180
- expect(['{&quot;error&quot;:&quot;rain!&quot;,&quot;detail&quot;:&quot;missing widget&quot;}',
181
- '{&quot;detail&quot;:&quot;missing widget&quot;,&quot;error&quot;:&quot;rain!&quot;}']).to include(last_response.body)
182
- end
183
- end
184
-
185
- context do
186
- let(:running_app) { exception_app }
187
- let(:options) { { rescue_all: true, format: :xml } }
188
-
189
- it 'is possible to return errors in xml format' do
190
- get '/'
191
- expect(last_response.body).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <message>rain!</message>\n</error>\n")
192
- end
193
- end
194
-
195
- context do
196
- let(:running_app) { error_hash_app }
197
- let(:options) { { rescue_all: true, format: :xml } }
198
-
199
- it 'is possible to return hash errors in xml format' do
200
- get '/'
201
- expect(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <detail>missing widget</detail>\n <error>rain!</error>\n</error>\n",
202
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <error>rain!</error>\n <detail>missing widget</detail>\n</error>\n"]).to include(last_response.body)
203
- end
204
- end
205
-
206
- context do
207
- let(:running_app) { exception_app }
208
- let(:options) do
209
- {
210
- rescue_all: true,
211
- format: :custom,
212
- error_formatters: {
213
- custom: lambda do |message, _backtrace, _options, _env, _original_exception|
214
- { custom_formatter: message }.inspect
215
- end
216
- }
217
- }
218
- end
219
-
220
- it 'is possible to specify a custom formatter' do
221
- get '/'
222
- expect(last_response.body).to eq('{:custom_formatter=&gt;&quot;rain!&quot;}')
223
- end
224
- end
225
-
226
- context do
227
- let(:running_app) { access_denied_app }
228
- let(:options) { {} }
229
-
230
- it 'does not trap regular error! codes' do
231
- get '/'
232
- expect(last_response.status).to eq(401)
233
- end
234
- end
235
-
236
- context do
237
- let(:running_app) { custom_error_app }
238
- let(:options) { { rescue_all: false } }
239
-
240
- it 'responds to custom Grape exceptions appropriately' do
241
- get '/'
242
- expect(last_response.status).to eq(400)
243
- expect(last_response.body).to eq('failed validation')
244
- end
245
- end
246
-
247
- context 'with rescue_options :backtrace and :exception set to true' do
248
- let(:running_app) { exception_app }
249
- let(:options) do
250
- {
251
- rescue_all: true,
252
- format: :json,
253
- rescue_options: { backtrace: true, original_exception: true }
254
- }
255
- end
256
-
257
- it 'is possible to return the backtrace and the original exception in json format' do
258
- get '/'
259
- expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original_exception', 'RuntimeError')
260
- end
261
- end
262
-
263
- context do
264
- let(:running_app) { exception_app }
265
- let(:options) do
266
- {
267
- rescue_all: true,
268
- format: :xml,
269
- rescue_options: { backtrace: true, original_exception: true }
270
- }
271
- end
272
-
273
- it 'is possible to return the backtrace and the original exception in xml format' do
274
- get '/'
275
- expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original-exception', 'RuntimeError')
276
- end
277
- end
278
-
279
- context do
280
- let(:running_app) { exception_app }
281
- let(:options) do
282
- {
283
- rescue_all: true,
284
- format: :txt,
285
- rescue_options: { backtrace: true, original_exception: true }
286
- }
287
- end
288
-
289
- it 'is possible to return the backtrace and the original exception in txt format' do
290
- get '/'
291
- expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original exception', 'RuntimeError')
292
- end
293
- end
294
- end