grape 1.8.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +65 -1
  3. data/README.md +377 -334
  4. data/UPGRADING.md +231 -6
  5. data/grape.gemspec +6 -10
  6. data/lib/grape/api/instance.rb +13 -10
  7. data/lib/grape/api.rb +17 -8
  8. data/lib/grape/content_types.rb +0 -2
  9. data/lib/grape/cookies.rb +2 -1
  10. data/lib/grape/dry_types.rb +0 -2
  11. data/lib/grape/dsl/desc.rb +23 -21
  12. data/lib/grape/dsl/headers.rb +1 -1
  13. data/lib/grape/dsl/inside_route.rb +47 -22
  14. data/lib/grape/dsl/parameters.rb +4 -3
  15. data/lib/grape/dsl/routing.rb +20 -4
  16. data/lib/grape/dsl/validations.rb +13 -0
  17. data/lib/grape/endpoint.rb +15 -10
  18. data/lib/grape/{util/env.rb → env.rb} +0 -5
  19. data/lib/grape/error_formatter/txt.rb +11 -10
  20. data/lib/grape/exceptions/base.rb +3 -3
  21. data/lib/grape/exceptions/missing_group_type.rb +1 -1
  22. data/lib/grape/exceptions/unsupported_group_type.rb +1 -1
  23. data/lib/grape/exceptions/validation.rb +0 -2
  24. data/lib/grape/exceptions/validation_array_errors.rb +1 -0
  25. data/lib/grape/exceptions/validation_errors.rb +1 -3
  26. data/lib/grape/extensions/hash.rb +5 -1
  27. data/lib/grape/http/headers.rb +18 -24
  28. data/lib/grape/{util/json.rb → json.rb} +1 -3
  29. data/lib/grape/locale/en.yml +3 -0
  30. data/lib/grape/middleware/auth/base.rb +0 -2
  31. data/lib/grape/middleware/auth/dsl.rb +0 -2
  32. data/lib/grape/middleware/auth/strategies.rb +1 -2
  33. data/lib/grape/middleware/base.rb +0 -2
  34. data/lib/grape/middleware/error.rb +55 -50
  35. data/lib/grape/middleware/formatter.rb +21 -18
  36. data/lib/grape/middleware/globals.rb +1 -3
  37. data/lib/grape/middleware/stack.rb +2 -3
  38. data/lib/grape/middleware/versioner/accept_version_header.rb +0 -2
  39. data/lib/grape/middleware/versioner/header.rb +17 -163
  40. data/lib/grape/middleware/versioner/param.rb +2 -4
  41. data/lib/grape/middleware/versioner/path.rb +1 -3
  42. data/lib/grape/namespace.rb +3 -4
  43. data/lib/grape/path.rb +24 -29
  44. data/lib/grape/railtie.rb +9 -0
  45. data/lib/grape/request.rb +3 -5
  46. data/lib/grape/router/base_route.rb +39 -0
  47. data/lib/grape/router/greedy_route.rb +20 -0
  48. data/lib/grape/router/pattern.rb +39 -30
  49. data/lib/grape/router/route.rb +22 -59
  50. data/lib/grape/router.rb +30 -36
  51. data/lib/grape/util/accept/header.rb +19 -0
  52. data/lib/grape/util/accept_header_handler.rb +105 -0
  53. data/lib/grape/util/base_inheritable.rb +4 -4
  54. data/lib/grape/util/cache.rb +0 -3
  55. data/lib/grape/util/endpoint_configuration.rb +1 -1
  56. data/lib/grape/util/header.rb +13 -0
  57. data/lib/grape/util/inheritable_values.rb +0 -2
  58. data/lib/grape/util/lazy/block.rb +29 -0
  59. data/lib/grape/util/lazy/object.rb +45 -0
  60. data/lib/grape/util/lazy/value.rb +38 -0
  61. data/lib/grape/util/lazy/value_array.rb +21 -0
  62. data/lib/grape/util/lazy/value_enumerable.rb +34 -0
  63. data/lib/grape/util/lazy/value_hash.rb +21 -0
  64. data/lib/grape/util/media_type.rb +70 -0
  65. data/lib/grape/util/reverse_stackable_values.rb +1 -6
  66. data/lib/grape/util/stackable_values.rb +1 -6
  67. data/lib/grape/util/strict_hash_configuration.rb +3 -3
  68. data/lib/grape/validations/attributes_doc.rb +38 -36
  69. data/lib/grape/validations/contract_scope.rb +71 -0
  70. data/lib/grape/validations/params_scope.rb +10 -9
  71. data/lib/grape/validations/types/array_coercer.rb +0 -2
  72. data/lib/grape/validations/types/build_coercer.rb +69 -71
  73. data/lib/grape/validations/types/dry_type_coercer.rb +1 -11
  74. data/lib/grape/validations/types/json.rb +0 -2
  75. data/lib/grape/validations/types/primitive_coercer.rb +0 -2
  76. data/lib/grape/validations/types/set_coercer.rb +0 -3
  77. data/lib/grape/validations/types.rb +0 -3
  78. data/lib/grape/validations/validators/base.rb +2 -1
  79. data/lib/grape/validations/validators/default_validator.rb +5 -1
  80. data/lib/grape/validations/validators/length_validator.rb +42 -0
  81. data/lib/grape/validations/validators/values_validator.rb +8 -3
  82. data/lib/grape/validations.rb +3 -7
  83. data/lib/grape/version.rb +1 -1
  84. data/lib/grape/{util/xml.rb → xml.rb} +1 -1
  85. data/lib/grape.rb +38 -269
  86. metadata +33 -274
  87. data/lib/grape/eager_load.rb +0 -20
  88. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
  89. data/lib/grape/router/attribute_translator.rb +0 -63
  90. data/lib/grape/util/lazy_block.rb +0 -27
  91. data/lib/grape/util/lazy_object.rb +0 -43
  92. data/lib/grape/util/lazy_value.rb +0 -91
  93. data/spec/grape/api/custom_validations_spec.rb +0 -213
  94. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  95. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  96. data/spec/grape/api/documentation_spec.rb +0 -59
  97. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  98. data/spec/grape/api/instance_spec.rb +0 -103
  99. data/spec/grape/api/invalid_format_spec.rb +0 -45
  100. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  101. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  102. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  103. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  104. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  105. data/spec/grape/api/recognize_path_spec.rb +0 -21
  106. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  107. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  108. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  109. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  110. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  111. data/spec/grape/api_remount_spec.rb +0 -509
  112. data/spec/grape/api_spec.rb +0 -4356
  113. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  114. data/spec/grape/dsl/desc_spec.rb +0 -98
  115. data/spec/grape/dsl/headers_spec.rb +0 -62
  116. data/spec/grape/dsl/helpers_spec.rb +0 -100
  117. data/spec/grape/dsl/inside_route_spec.rb +0 -531
  118. data/spec/grape/dsl/logger_spec.rb +0 -24
  119. data/spec/grape/dsl/middleware_spec.rb +0 -60
  120. data/spec/grape/dsl/parameters_spec.rb +0 -180
  121. data/spec/grape/dsl/request_response_spec.rb +0 -225
  122. data/spec/grape/dsl/routing_spec.rb +0 -275
  123. data/spec/grape/dsl/settings_spec.rb +0 -261
  124. data/spec/grape/dsl/validations_spec.rb +0 -55
  125. data/spec/grape/endpoint/declared_spec.rb +0 -846
  126. data/spec/grape/endpoint_spec.rb +0 -1085
  127. data/spec/grape/entity_spec.rb +0 -336
  128. data/spec/grape/exceptions/base_spec.rb +0 -81
  129. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
  130. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  131. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  132. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  133. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  134. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
  135. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  136. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  137. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  138. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  139. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
  140. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  141. data/spec/grape/exceptions/validation_spec.rb +0 -19
  142. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  143. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  144. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  145. data/spec/grape/grape_spec.rb +0 -9
  146. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  147. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  148. data/spec/grape/integration/rack_spec.rb +0 -51
  149. data/spec/grape/loading_spec.rb +0 -44
  150. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  151. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  152. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  153. data/spec/grape/middleware/base_spec.rb +0 -221
  154. data/spec/grape/middleware/error_spec.rb +0 -85
  155. data/spec/grape/middleware/exception_spec.rb +0 -294
  156. data/spec/grape/middleware/formatter_spec.rb +0 -461
  157. data/spec/grape/middleware/globals_spec.rb +0 -30
  158. data/spec/grape/middleware/stack_spec.rb +0 -155
  159. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  160. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  161. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  162. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  163. data/spec/grape/middleware/versioner_spec.rb +0 -21
  164. data/spec/grape/named_api_spec.rb +0 -19
  165. data/spec/grape/parser_spec.rb +0 -86
  166. data/spec/grape/path_spec.rb +0 -252
  167. data/spec/grape/presenters/presenter_spec.rb +0 -71
  168. data/spec/grape/request_spec.rb +0 -126
  169. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  170. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  171. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  172. data/spec/grape/util/stackable_values_spec.rb +0 -128
  173. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  174. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  175. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  176. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
  177. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  178. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
  179. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  180. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  181. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  182. data/spec/grape/validations/types_spec.rb +0 -111
  183. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  184. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  185. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  186. data/spec/grape/validations/validators/base_spec.rb +0 -38
  187. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  188. data/spec/grape/validations/validators/default_spec.rb +0 -463
  189. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  190. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  191. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  192. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  193. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  194. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  195. data/spec/grape/validations/validators/values_spec.rb +0 -733
  196. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  197. data/spec/grape/validations_spec.rb +0 -2030
  198. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  199. data/spec/integration/multi_json/json_spec.rb +0 -7
  200. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  201. data/spec/shared/deprecated_class_examples.rb +0 -16
  202. data/spec/shared/versioning_examples.rb +0 -215
  203. data/spec/spec_helper.rb +0 -52
  204. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  205. data/spec/support/chunks.rb +0 -14
  206. data/spec/support/content_type_helpers.rb +0 -15
  207. data/spec/support/endpoint_faker.rb +0 -25
  208. data/spec/support/file_streamer.rb +0 -13
  209. data/spec/support/integer_helpers.rb +0 -13
  210. data/spec/support/versioned_helpers.rb +0 -55
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module DSL
5
- module ParametersSpec
6
- class Dummy
7
- include Grape::DSL::Parameters
8
- attr_accessor :api, :element, :parent
9
-
10
- def validate_attributes(*args)
11
- @validate_attributes = *args
12
- end
13
-
14
- def validate_attributes_reader
15
- @validate_attributes
16
- end
17
-
18
- def push_declared_params(args, **_opts)
19
- @push_declared_params = args
20
- end
21
-
22
- def push_declared_params_reader
23
- @push_declared_params
24
- end
25
-
26
- def validates(*args)
27
- @validates = *args
28
- end
29
-
30
- def validates_reader
31
- @validates
32
- end
33
-
34
- def new_group_scope(args)
35
- @group = args.clone.first
36
- yield
37
- end
38
-
39
- def extract_message_option(attrs)
40
- return nil unless attrs.is_a?(Array)
41
-
42
- opts = attrs.last.is_a?(Hash) ? attrs.pop : {}
43
- opts.key?(:message) && !opts[:message].nil? ? opts.delete(:message) : nil
44
- end
45
- end
46
- end
47
-
48
- describe Parameters do
49
- subject { ParametersSpec::Dummy.new }
50
-
51
- describe '#use' do
52
- before do
53
- allow_message_expectations_on_nil
54
- allow(subject.api).to receive(:namespace_stackable).with(:named_params)
55
- end
56
-
57
- let(:options) { { option: 'value' } }
58
- let(:named_params) { { params_group: proc {} } }
59
-
60
- it 'calls processes associated with named params' do
61
- allow(subject.api).to receive(:namespace_stackable_with_hash).and_return(named_params)
62
- expect(subject).to receive(:instance_exec).with(options).and_yield
63
- subject.use :params_group, options
64
- end
65
-
66
- it 'raises error when non-existent named param is called' do
67
- allow(subject.api).to receive(:namespace_stackable_with_hash).and_return({})
68
- expect { subject.use :params_group }.to raise_error('Params :params_group not found!')
69
- end
70
- end
71
-
72
- describe '#use_scope' do
73
- it 'is alias to #use' do
74
- expect(subject.method(:use_scope)).to eq subject.method(:use)
75
- end
76
- end
77
-
78
- describe '#includes' do
79
- it 'is alias to #use' do
80
- expect(subject.method(:includes)).to eq subject.method(:use)
81
- end
82
- end
83
-
84
- describe '#requires' do
85
- it 'adds a required parameter' do
86
- subject.requires :id, type: Integer, desc: 'Identity.'
87
-
88
- expect(subject.validate_attributes_reader).to eq([[:id], { type: Integer, desc: 'Identity.', presence: { value: true, message: nil } }])
89
- expect(subject.push_declared_params_reader).to eq([:id])
90
- end
91
- end
92
-
93
- describe '#optional' do
94
- it 'adds an optional parameter' do
95
- subject.optional :id, type: Integer, desc: 'Identity.'
96
-
97
- expect(subject.validate_attributes_reader).to eq([[:id], { type: Integer, desc: 'Identity.' }])
98
- expect(subject.push_declared_params_reader).to eq([:id])
99
- end
100
- end
101
-
102
- describe '#with' do
103
- it 'creates a scope with group attributes' do
104
- subject.with(type: Integer) { subject.optional :id, desc: 'Identity.' }
105
-
106
- expect(subject.validate_attributes_reader).to eq([[:id], { type: Integer, desc: 'Identity.' }])
107
- expect(subject.push_declared_params_reader).to eq([:id])
108
- end
109
- end
110
-
111
- describe '#mutually_exclusive' do
112
- it 'adds an mutally exclusive parameter validation' do
113
- subject.mutually_exclusive :media, :audio
114
-
115
- expect(subject.validates_reader).to eq([%i[media audio], { mutual_exclusion: { value: true, message: nil } }])
116
- end
117
- end
118
-
119
- describe '#exactly_one_of' do
120
- it 'adds an exactly of one parameter validation' do
121
- subject.exactly_one_of :media, :audio
122
-
123
- expect(subject.validates_reader).to eq([%i[media audio], { exactly_one_of: { value: true, message: nil } }])
124
- end
125
- end
126
-
127
- describe '#at_least_one_of' do
128
- it 'adds an at least one of parameter validation' do
129
- subject.at_least_one_of :media, :audio
130
-
131
- expect(subject.validates_reader).to eq([%i[media audio], { at_least_one_of: { value: true, message: nil } }])
132
- end
133
- end
134
-
135
- describe '#all_or_none_of' do
136
- it 'adds an all or none of parameter validation' do
137
- subject.all_or_none_of :media, :audio
138
-
139
- expect(subject.validates_reader).to eq([%i[media audio], { all_or_none_of: { value: true, message: nil } }])
140
- end
141
- end
142
-
143
- describe '#group' do
144
- it 'is alias to #requires' do
145
- expect(subject.method(:group)).to eq subject.method(:requires)
146
- end
147
- end
148
-
149
- describe '#params' do
150
- it 'inherits params from parent' do
151
- parent_params = { foo: 'bar' }
152
- subject.parent = Object.new
153
- allow(subject.parent).to receive(:params).and_return(parent_params)
154
- expect(subject.params({})).to eq parent_params
155
- end
156
-
157
- describe 'when params argument is an array of hashes' do
158
- it 'returns values of each hash for @element key' do
159
- subject.element = :foo
160
- expect(subject.params([{ foo: 'bar' }, { foo: 'baz' }])).to eq(%w[bar baz])
161
- end
162
- end
163
-
164
- describe 'when params argument is a hash' do
165
- it 'returns value for @element key' do
166
- subject.element = :foo
167
- expect(subject.params(foo: 'bar')).to eq('bar')
168
- end
169
- end
170
-
171
- describe 'when params argument is not a array or a hash' do
172
- it 'returns empty hash' do
173
- subject.element = Object.new
174
- expect(subject.params(Object.new)).to eq({})
175
- end
176
- end
177
- end
178
- end
179
- end
180
- end
@@ -1,225 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module DSL
5
- module RequestResponseSpec
6
- class Dummy
7
- include Grape::DSL::RequestResponse
8
-
9
- def self.set(key, value)
10
- settings[key.to_sym] = value
11
- end
12
-
13
- def self.imbue(key, value)
14
- settings.imbue(key, value)
15
- end
16
- end
17
- end
18
-
19
- describe RequestResponse do
20
- subject { Class.new(RequestResponseSpec::Dummy) }
21
-
22
- let(:c_type) { 'application/json' }
23
- let(:format) { 'txt' }
24
-
25
- describe '.default_format' do
26
- it 'sets the default format' do
27
- expect(subject).to receive(:namespace_inheritable).with(:default_format, :format)
28
- subject.default_format :format
29
- end
30
-
31
- it 'returns the format without paramter' do
32
- subject.default_format :format
33
-
34
- expect(subject.default_format).to eq :format
35
- end
36
- end
37
-
38
- describe '.format' do
39
- it 'sets a new format' do
40
- expect(subject).to receive(:namespace_inheritable).with(:format, format.to_sym)
41
- expect(subject).to receive(:namespace_inheritable).with(:default_error_formatter, Grape::ErrorFormatter::Txt)
42
-
43
- subject.format format
44
- end
45
- end
46
-
47
- describe '.formatter' do
48
- it 'sets the formatter for a content type' do
49
- expect(subject).to receive(:namespace_stackable).with(:formatters, c_type.to_sym => :formatter)
50
- subject.formatter c_type, :formatter
51
- end
52
- end
53
-
54
- describe '.parser' do
55
- it 'sets a parser for a content type' do
56
- expect(subject).to receive(:namespace_stackable).with(:parsers, c_type.to_sym => :parser)
57
- subject.parser c_type, :parser
58
- end
59
- end
60
-
61
- describe '.default_error_formatter' do
62
- it 'sets a new error formatter' do
63
- expect(subject).to receive(:namespace_inheritable).with(:default_error_formatter, Grape::ErrorFormatter::Json)
64
- subject.default_error_formatter :json
65
- end
66
- end
67
-
68
- describe '.error_formatter' do
69
- it 'sets a error_formatter' do
70
- format = 'txt'
71
- expect(subject).to receive(:namespace_stackable).with(:error_formatters, format.to_sym => :error_formatter)
72
- subject.error_formatter format, :error_formatter
73
- end
74
-
75
- it 'understands syntactic sugar' do
76
- expect(subject).to receive(:namespace_stackable).with(:error_formatters, format.to_sym => :error_formatter)
77
- subject.error_formatter format, with: :error_formatter
78
- end
79
- end
80
-
81
- describe '.content_type' do
82
- it 'sets a content type for a format' do
83
- expect(subject).to receive(:namespace_stackable).with(:content_types, format.to_sym => c_type)
84
- subject.content_type format, c_type
85
- end
86
- end
87
-
88
- describe '.content_types' do
89
- it 'returns all content types' do
90
- expect(subject.content_types).to eq(xml: 'application/xml',
91
- serializable_hash: 'application/json',
92
- json: 'application/json',
93
- txt: 'text/plain',
94
- binary: 'application/octet-stream')
95
- end
96
- end
97
-
98
- describe '.default_error_status' do
99
- it 'sets a default error status' do
100
- expect(subject).to receive(:namespace_inheritable).with(:default_error_status, 500)
101
- subject.default_error_status 500
102
- end
103
- end
104
-
105
- describe '.rescue_from' do
106
- describe ':all' do
107
- it 'sets rescue all to true' do
108
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
109
- expect(subject).to receive(:namespace_inheritable).with(:all_rescue_handler, nil)
110
- subject.rescue_from :all
111
- end
112
-
113
- it 'sets given proc as rescue handler' do
114
- rescue_handler_proc = proc {}
115
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
116
- expect(subject).to receive(:namespace_inheritable).with(:all_rescue_handler, rescue_handler_proc)
117
- subject.rescue_from :all, rescue_handler_proc
118
- end
119
-
120
- it 'sets given block as rescue handler' do
121
- rescue_handler_proc = proc {}
122
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
123
- expect(subject).to receive(:namespace_inheritable).with(:all_rescue_handler, rescue_handler_proc)
124
- subject.rescue_from :all, &rescue_handler_proc
125
- end
126
-
127
- it 'sets a rescue handler declared through :with option' do
128
- with_block = -> { 'hello' }
129
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
130
- expect(subject).to receive(:namespace_inheritable).with(:all_rescue_handler, an_instance_of(Proc))
131
- subject.rescue_from :all, with: with_block
132
- end
133
-
134
- it 'abort if :with option value is not Symbol, String or Proc' do
135
- expect { subject.rescue_from :all, with: 1234 }.to raise_error(ArgumentError, "with: #{integer_class_name}, expected Symbol, String or Proc")
136
- end
137
-
138
- it 'abort if both :with option and block are passed' do
139
- expect do
140
- subject.rescue_from :all, with: -> { 'hello' } do
141
- error!('bye')
142
- end
143
- end.to raise_error(ArgumentError, 'both :with option and block cannot be passed')
144
- end
145
- end
146
-
147
- describe ':grape_exceptions' do
148
- it 'sets rescue all to true' do
149
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
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)
152
- subject.rescue_from :grape_exceptions
153
- end
154
-
155
- it 'sets given proc as rescue handler' do
156
- rescue_handler_proc = proc {}
157
- expect(subject).to receive(:namespace_inheritable).with(:rescue_all, true)
158
- expect(subject).to receive(:namespace_inheritable).with(:rescue_grape_exceptions, true)
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
177
- end
178
- end
179
-
180
- describe 'list of exceptions is passed' do
181
- it 'sets hash of exceptions as rescue handlers' do
182
- expect(subject).to receive(:namespace_reverse_stackable).with(:rescue_handlers, { StandardError => nil })
183
- expect(subject).to receive(:namespace_stackable).with(:rescue_options, {})
184
- subject.rescue_from StandardError
185
- end
186
-
187
- it 'rescues only base handlers if rescue_subclasses: false option is passed' do
188
- expect(subject).to receive(:namespace_reverse_stackable).with(:base_only_rescue_handlers, { StandardError => nil })
189
- expect(subject).to receive(:namespace_stackable).with(:rescue_options, { rescue_subclasses: false })
190
- subject.rescue_from StandardError, rescue_subclasses: false
191
- end
192
-
193
- it 'sets given proc as rescue handler for each key in hash' do
194
- rescue_handler_proc = proc {}
195
- expect(subject).to receive(:namespace_reverse_stackable).with(:rescue_handlers, { StandardError => rescue_handler_proc })
196
- expect(subject).to receive(:namespace_stackable).with(:rescue_options, {})
197
- subject.rescue_from StandardError, rescue_handler_proc
198
- end
199
-
200
- it 'sets given block as rescue handler for each key in hash' do
201
- rescue_handler_proc = proc {}
202
- expect(subject).to receive(:namespace_reverse_stackable).with(:rescue_handlers, { StandardError => rescue_handler_proc })
203
- expect(subject).to receive(:namespace_stackable).with(:rescue_options, {})
204
- subject.rescue_from StandardError, &rescue_handler_proc
205
- end
206
-
207
- it 'sets a rescue handler declared through :with option for each key in hash' do
208
- with_block = -> { 'hello' }
209
- expect(subject).to receive(:namespace_reverse_stackable).with(:rescue_handlers, { StandardError => an_instance_of(Proc) })
210
- expect(subject).to receive(:namespace_stackable).with(:rescue_options, {})
211
- subject.rescue_from StandardError, with: with_block
212
- end
213
- end
214
- end
215
-
216
- describe '.represent' do
217
- it 'sets a presenter for a class' do
218
- presenter = Class.new
219
- expect(subject).to receive(:namespace_stackable).with(:representations, ThisClass: presenter)
220
- subject.represent :ThisClass, with: presenter
221
- end
222
- end
223
- end
224
- end
225
- end
@@ -1,275 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module DSL
5
- module RoutingSpec
6
- class Dummy
7
- include Grape::DSL::Routing
8
- end
9
- end
10
-
11
- describe Routing do
12
- subject { Class.new(RoutingSpec::Dummy) }
13
-
14
- let(:proc) { -> {} }
15
- let(:options) { { a: :b } }
16
- let(:path) { '/dummy' }
17
-
18
- describe '.version' do
19
- it 'sets a version for route' do
20
- version = 'v1'
21
- expect(subject).to receive(:namespace_inheritable).with(:version, [version])
22
- expect(subject).to receive(:namespace_inheritable).with(:version_options, { using: :path })
23
- expect(subject.version(version)).to eq(version)
24
- end
25
- end
26
-
27
- describe '.prefix' do
28
- it 'sets a prefix for route' do
29
- prefix = '/api'
30
- expect(subject).to receive(:namespace_inheritable).with(:root_prefix, prefix)
31
- subject.prefix prefix
32
- end
33
- end
34
-
35
- describe '.scope' do
36
- it 'create a scope without affecting the URL' do
37
- expect(subject).to receive(:within_namespace)
38
- subject.scope {}
39
- end
40
- end
41
-
42
- describe '.do_not_route_head!' do
43
- it 'sets do not route head option' do
44
- expect(subject).to receive(:namespace_inheritable).with(:do_not_route_head, true)
45
- subject.do_not_route_head!
46
- end
47
- end
48
-
49
- describe '.do_not_route_options!' do
50
- it 'sets do not route options option' do
51
- expect(subject).to receive(:namespace_inheritable).with(:do_not_route_options, true)
52
- subject.do_not_route_options!
53
- end
54
- end
55
-
56
- describe '.mount' do
57
- it 'mounts on a nested path' do
58
- subject = Class.new(Grape::API)
59
- app1 = Class.new(Grape::API)
60
- app2 = Class.new(Grape::API)
61
- app2.get '/nice' do
62
- 'play'
63
- end
64
-
65
- subject.mount app1 => '/app1'
66
- app1.mount app2 => '/app2'
67
-
68
- expect(subject.inheritable_setting.to_hash[:namespace]).to eq({})
69
- expect(subject.inheritable_setting.to_hash[:namespace_inheritable]).to eq({})
70
- expect(app1.inheritable_setting.to_hash[:namespace_stackable]).to eq(mount_path: ['/app1'])
71
-
72
- expect(app2.inheritable_setting.to_hash[:namespace_stackable]).to eq(mount_path: ['/app1', '/app2'])
73
- end
74
-
75
- it 'mounts multiple routes at once' do
76
- base_app = Class.new(Grape::API)
77
- app1 = Class.new(Grape::API)
78
- app2 = Class.new(Grape::API)
79
- base_app.mount(app1 => '/app1', app2 => '/app2')
80
-
81
- expect(app1.inheritable_setting.to_hash[:namespace_stackable]).to eq(mount_path: ['/app1'])
82
- expect(app2.inheritable_setting.to_hash[:namespace_stackable]).to eq(mount_path: ['/app2'])
83
- end
84
- end
85
-
86
- describe '.route' do
87
- before do
88
- allow(subject).to receive(:endpoints).and_return([])
89
- allow(subject).to receive(:route_end)
90
- allow(subject).to receive(:reset_validations!)
91
- end
92
-
93
- it 'marks end of the route' do
94
- expect(subject).to receive(:route_end)
95
- subject.route(:any)
96
- end
97
-
98
- it 'resets validations' do
99
- expect(subject).to receive(:reset_validations!)
100
- subject.route(:any)
101
- end
102
-
103
- it 'defines a new endpoint' do
104
- expect { subject.route(:any) }
105
- .to change { subject.endpoints.count }.from(0).to(1)
106
- end
107
-
108
- it 'does not duplicate identical endpoints' do
109
- subject.route(:any)
110
- expect { subject.route(:any) }
111
- .not_to change(subject.endpoints, :count)
112
- end
113
-
114
- it 'generates correct endpoint options' do
115
- allow(subject).to receive(:route_setting).with(:description).and_return(fiz: 'baz')
116
- allow(subject).to receive(:namespace_stackable_with_hash).and_return(nuz: 'naz')
117
-
118
- expect(Grape::Endpoint).to receive(:new) do |_inheritable_setting, endpoint_options|
119
- expect(endpoint_options[:method]).to eq :get
120
- expect(endpoint_options[:path]).to eq '/foo'
121
- expect(endpoint_options[:for]).to eq subject
122
- expect(endpoint_options[:route_options]).to eq(foo: 'bar', fiz: 'baz', params: { nuz: 'naz' })
123
- end.and_yield
124
-
125
- subject.route(:get, '/foo', { foo: 'bar' }, &proc {})
126
- end
127
- end
128
-
129
- describe '.get' do
130
- it 'delegates to .route' do
131
- expect(subject).to receive(:route).with('GET', path, options)
132
- subject.get path, options, &proc
133
- end
134
- end
135
-
136
- describe '.post' do
137
- it 'delegates to .route' do
138
- expect(subject).to receive(:route).with('POST', path, options)
139
- subject.post path, options, &proc
140
- end
141
- end
142
-
143
- describe '.put' do
144
- it 'delegates to .route' do
145
- expect(subject).to receive(:route).with('PUT', path, options)
146
- subject.put path, options, &proc
147
- end
148
- end
149
-
150
- describe '.head' do
151
- it 'delegates to .route' do
152
- expect(subject).to receive(:route).with('HEAD', path, options)
153
- subject.head path, options, &proc
154
- end
155
- end
156
-
157
- describe '.delete' do
158
- it 'delegates to .route' do
159
- expect(subject).to receive(:route).with('DELETE', path, options)
160
- subject.delete path, options, &proc
161
- end
162
- end
163
-
164
- describe '.options' do
165
- it 'delegates to .route' do
166
- expect(subject).to receive(:route).with('OPTIONS', path, options)
167
- subject.options path, options, &proc
168
- end
169
- end
170
-
171
- describe '.patch' do
172
- it 'delegates to .route' do
173
- expect(subject).to receive(:route).with('PATCH', path, options)
174
- subject.patch path, options, &proc
175
- end
176
- end
177
-
178
- describe '.namespace' do
179
- let(:new_namespace) { Object.new }
180
-
181
- it 'creates a new namespace with given name and options' do
182
- expect(subject).to receive(:within_namespace).and_yield
183
- expect(subject).to receive(:nest).and_yield
184
- expect(Namespace).to receive(:new).with(:foo, foo: 'bar').and_return(new_namespace)
185
- expect(subject).to receive(:namespace_stackable).with(:namespace, new_namespace)
186
-
187
- subject.namespace :foo, foo: 'bar', &proc {}
188
- end
189
-
190
- it 'calls #joined_space_path on Namespace' do
191
- result_of_namspace_stackable = Object.new
192
- allow(subject).to receive(:namespace_stackable).and_return(result_of_namspace_stackable)
193
- expect(Namespace).to receive(:joined_space_path).with(result_of_namspace_stackable)
194
- subject.namespace
195
- end
196
- end
197
-
198
- describe '.group' do
199
- it 'is alias to #namespace' do
200
- expect(subject.method(:group)).to eq subject.method(:namespace)
201
- end
202
- end
203
-
204
- describe '.resource' do
205
- it 'is alias to #namespace' do
206
- expect(subject.method(:resource)).to eq subject.method(:namespace)
207
- end
208
- end
209
-
210
- describe '.resources' do
211
- it 'is alias to #namespace' do
212
- expect(subject.method(:resources)).to eq subject.method(:namespace)
213
- end
214
- end
215
-
216
- describe '.segment' do
217
- it 'is alias to #namespace' do
218
- expect(subject.method(:segment)).to eq subject.method(:namespace)
219
- end
220
- end
221
-
222
- describe '.routes' do
223
- let(:routes) { Object.new }
224
-
225
- it 'returns value received from #prepare_routes' do
226
- expect(subject).to receive(:prepare_routes).and_return(routes)
227
- expect(subject.routes).to eq routes
228
- end
229
-
230
- context 'when #routes was already called once' do
231
- before do
232
- allow(subject).to receive(:prepare_routes).and_return(routes)
233
- subject.routes
234
- end
235
-
236
- it 'does not call prepare_routes again' do
237
- expect(subject).not_to receive(:prepare_routes)
238
- expect(subject.routes).to eq routes
239
- end
240
- end
241
- end
242
-
243
- describe '.route_param' do
244
- let!(:options) { { requirements: regex } }
245
- let(:regex) { /(.*)/ }
246
-
247
- it 'calls #namespace with given params' do
248
- expect(subject).to receive(:namespace).with(':foo', {}).and_yield
249
- subject.route_param('foo', {}, &proc {})
250
- end
251
-
252
- it 'nests requirements option under param name' do
253
- expect(subject).to receive(:namespace) do |_param, options|
254
- expect(options[:requirements][:foo]).to eq regex
255
- end
256
- subject.route_param('foo', options, &proc {})
257
- end
258
-
259
- it 'does not modify options parameter' do
260
- allow(subject).to receive(:namespace)
261
- expect { subject.route_param('foo', options, &proc {}) }
262
- .not_to change { options }
263
- end
264
- end
265
-
266
- describe '.versions' do
267
- it 'returns last defined version' do
268
- subject.version 'v1'
269
- subject.version 'v2'
270
- expect(subject.version).to eq('v2')
271
- end
272
- end
273
- end
274
- end
275
- end