praxis 2.0.pre.18 → 2.0.pre.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +54 -0
  3. data/.simplecov +3 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +6 -0
  6. data/CONTRIBUTING.md +2 -79
  7. data/Gemfile +5 -1
  8. data/Guardfile +6 -4
  9. data/LICENSE +0 -2
  10. data/MAINTAINERS.md +1 -0
  11. data/README.md +15 -22
  12. data/Rakefile +4 -2
  13. data/bin/praxis +55 -58
  14. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -6
  15. data/lib/praxis/action_definition.rb +64 -94
  16. data/lib/praxis/api_definition.rb +21 -29
  17. data/lib/praxis/api_general_info.rb +55 -66
  18. data/lib/praxis/application.rb +15 -32
  19. data/lib/praxis/blueprint.rb +64 -73
  20. data/lib/praxis/bootloader.rb +24 -33
  21. data/lib/praxis/bootloader_stages/environment.rb +5 -10
  22. data/lib/praxis/bootloader_stages/file_loader.rb +3 -6
  23. data/lib/praxis/bootloader_stages/plugin_config_load.rb +4 -6
  24. data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +2 -2
  25. data/lib/praxis/bootloader_stages/plugin_loader.rb +3 -7
  26. data/lib/praxis/bootloader_stages/plugin_setup.rb +3 -3
  27. data/lib/praxis/bootloader_stages/routing.rb +5 -8
  28. data/lib/praxis/bootloader_stages/subgroup_loader.rb +2 -10
  29. data/lib/praxis/bootloader_stages/warn_unloaded_files.rb +15 -19
  30. data/lib/praxis/callbacks.rb +12 -11
  31. data/lib/praxis/collection.rb +10 -13
  32. data/lib/praxis/config.rb +17 -28
  33. data/lib/praxis/config_hash.rb +2 -1
  34. data/lib/praxis/controller.rb +7 -6
  35. data/lib/praxis/dispatcher.rb +34 -42
  36. data/lib/praxis/docs/open_api/info_object.rb +11 -8
  37. data/lib/praxis/docs/open_api/media_type_object.rb +18 -17
  38. data/lib/praxis/docs/open_api/operation_object.rb +6 -3
  39. data/lib/praxis/docs/open_api/parameter_object.rb +17 -14
  40. data/lib/praxis/docs/open_api/paths_object.rb +11 -9
  41. data/lib/praxis/docs/open_api/request_body_object.rb +14 -13
  42. data/lib/praxis/docs/open_api/response_object.rb +24 -18
  43. data/lib/praxis/docs/open_api/responses_object.rb +3 -1
  44. data/lib/praxis/docs/open_api/schema_object.rb +16 -16
  45. data/lib/praxis/docs/open_api/server_object.rb +5 -2
  46. data/lib/praxis/docs/open_api/tag_object.rb +6 -3
  47. data/lib/praxis/docs/open_api_generator.rb +92 -95
  48. data/lib/praxis/endpoint_definition.rb +60 -77
  49. data/lib/praxis/error_handler.rb +2 -2
  50. data/lib/praxis/exception.rb +2 -0
  51. data/lib/praxis/exceptions/config.rb +3 -1
  52. data/lib/praxis/exceptions/config_load.rb +2 -0
  53. data/lib/praxis/exceptions/config_validation.rb +3 -1
  54. data/lib/praxis/exceptions/invalid_configuration.rb +3 -1
  55. data/lib/praxis/exceptions/invalid_response.rb +3 -1
  56. data/lib/praxis/exceptions/invalid_trait.rb +3 -1
  57. data/lib/praxis/exceptions/stage_not_found.rb +3 -1
  58. data/lib/praxis/exceptions/validation.rb +4 -3
  59. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +163 -149
  60. data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +18 -13
  61. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +13 -9
  62. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +14 -11
  63. data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +12 -9
  64. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +8 -5
  65. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +89 -65
  66. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +68 -62
  67. data/lib/praxis/extensions/attribute_filtering.rb +3 -1
  68. data/lib/praxis/extensions/field_expansion.rb +6 -4
  69. data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +10 -8
  70. data/lib/praxis/extensions/field_selection/field_selector.rb +91 -92
  71. data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +12 -12
  72. data/lib/praxis/extensions/field_selection.rb +3 -1
  73. data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +6 -4
  74. data/lib/praxis/extensions/pagination/header_generator.rb +16 -11
  75. data/lib/praxis/extensions/pagination/ordering_params.rb +29 -28
  76. data/lib/praxis/extensions/pagination/pagination_handler.rb +44 -42
  77. data/lib/praxis/extensions/pagination/pagination_params.rb +29 -48
  78. data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +8 -7
  79. data/lib/praxis/extensions/pagination.rb +10 -15
  80. data/lib/praxis/extensions/rails_compat/request_methods.rb +3 -4
  81. data/lib/praxis/extensions/rails_compat.rb +2 -0
  82. data/lib/praxis/extensions/rendering.rb +12 -12
  83. data/lib/praxis/field_expander.rb +8 -9
  84. data/lib/praxis/file_group.rb +8 -12
  85. data/lib/praxis/finalizable.rb +1 -0
  86. data/lib/praxis/handlers/json.rb +5 -2
  87. data/lib/praxis/handlers/plain.rb +2 -1
  88. data/lib/praxis/handlers/www_form.rb +6 -3
  89. data/lib/praxis/handlers/{xml-sample.rb → xml_sample.rb} +26 -22
  90. data/lib/praxis/mapper/active_model_compat.rb +13 -10
  91. data/lib/praxis/mapper/resource.rb +171 -180
  92. data/lib/praxis/mapper/selector_generator.rb +106 -112
  93. data/lib/praxis/mapper/sequel_compat.rb +70 -67
  94. data/lib/praxis/media_type.rb +2 -2
  95. data/lib/praxis/media_type_identifier.rb +26 -22
  96. data/lib/praxis/middleware_app.rb +18 -15
  97. data/lib/praxis/multipart/parser.rb +46 -51
  98. data/lib/praxis/multipart/part.rb +78 -110
  99. data/lib/praxis/notifications.rb +2 -4
  100. data/lib/praxis/plugin.rb +11 -18
  101. data/lib/praxis/plugin_concern.rb +12 -15
  102. data/lib/praxis/plugins/mapper_plugin.rb +15 -13
  103. data/lib/praxis/plugins/pagination_plugin.rb +8 -6
  104. data/lib/praxis/plugins/rails_plugin.rb +33 -28
  105. data/lib/praxis/renderer.rb +11 -15
  106. data/lib/praxis/request.rb +46 -47
  107. data/lib/praxis/request_stages/action.rb +4 -6
  108. data/lib/praxis/request_stages/load_request.rb +2 -4
  109. data/lib/praxis/request_stages/request_stage.rb +19 -23
  110. data/lib/praxis/request_stages/response.rb +4 -6
  111. data/lib/praxis/request_stages/validate.rb +3 -5
  112. data/lib/praxis/request_stages/validate_params_and_headers.rb +15 -16
  113. data/lib/praxis/request_stages/validate_payload.rb +25 -27
  114. data/lib/praxis/request_superclassing.rb +3 -3
  115. data/lib/praxis/resource_definition.rb +1 -0
  116. data/lib/praxis/response.rb +13 -25
  117. data/lib/praxis/response_definition.rb +77 -122
  118. data/lib/praxis/response_template.rb +11 -15
  119. data/lib/praxis/responses/http.rb +23 -44
  120. data/lib/praxis/responses/internal_server_error.rb +18 -21
  121. data/lib/praxis/responses/multipart_ok.rb +4 -9
  122. data/lib/praxis/responses/validation_error.rb +8 -15
  123. data/lib/praxis/route.rb +8 -10
  124. data/lib/praxis/router/rack.rb +13 -7
  125. data/lib/praxis/router/simple.rb +10 -5
  126. data/lib/praxis/router.rb +27 -34
  127. data/lib/praxis/routing_config.rb +52 -29
  128. data/lib/praxis/simple_media_type.rb +5 -8
  129. data/lib/praxis/stage.rb +17 -25
  130. data/lib/praxis/tasks/api_docs.rb +15 -15
  131. data/lib/praxis/tasks/console.rb +3 -1
  132. data/lib/praxis/tasks/environment.rb +2 -0
  133. data/lib/praxis/tasks/routes.rb +26 -24
  134. data/lib/praxis/tasks.rb +3 -1
  135. data/lib/praxis/trait.rb +37 -46
  136. data/lib/praxis/types/fuzzy_hash.rb +13 -14
  137. data/lib/praxis/types/media_type_common.rb +11 -10
  138. data/lib/praxis/types/multipart_array/part_definition.rb +14 -17
  139. data/lib/praxis/types/multipart_array.rb +88 -112
  140. data/lib/praxis/validation_handler.rb +5 -3
  141. data/lib/praxis/version.rb +3 -1
  142. data/lib/praxis.rb +4 -5
  143. data/praxis.gemspec +22 -21
  144. data/spec/functional_spec.rb +40 -52
  145. data/spec/praxis/action_definition_spec.rb +36 -46
  146. data/spec/praxis/api_definition_spec.rb +45 -47
  147. data/spec/praxis/api_general_info_spec.rb +28 -29
  148. data/spec/praxis/application_spec.rb +18 -14
  149. data/spec/praxis/blueprint_spec.rb +33 -34
  150. data/spec/praxis/bootloader_spec.rb +32 -30
  151. data/spec/praxis/callbacks_spec.rb +37 -37
  152. data/spec/praxis/collection_spec.rb +18 -25
  153. data/spec/praxis/config_hash_spec.rb +5 -4
  154. data/spec/praxis/config_spec.rb +27 -26
  155. data/spec/praxis/controller_spec.rb +8 -9
  156. data/spec/praxis/endpoint_definition_spec.rb +25 -32
  157. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +171 -114
  158. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +22 -21
  159. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +112 -60
  160. data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +37 -38
  161. data/spec/praxis/extensions/field_expansion_spec.rb +8 -10
  162. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +14 -13
  163. data/spec/praxis/extensions/field_selection/field_selector_spec.rb +9 -16
  164. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +50 -49
  165. data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +32 -31
  166. data/spec/praxis/extensions/rendering_spec.rb +9 -9
  167. data/spec/praxis/extensions/support/spec_resources_active_model.rb +32 -49
  168. data/spec/praxis/extensions/support/spec_resources_sequel.rb +48 -48
  169. data/spec/praxis/field_expander_spec.rb +6 -5
  170. data/spec/praxis/file_group_spec.rb +3 -1
  171. data/spec/praxis/handlers/json_spec.rb +6 -5
  172. data/spec/praxis/mapper/resource_spec.rb +27 -30
  173. data/spec/praxis/mapper/selector_generator_spec.rb +50 -50
  174. data/spec/praxis/media_type_identifier_spec.rb +13 -10
  175. data/spec/praxis/media_type_spec.rb +12 -12
  176. data/spec/praxis/middleware_app_spec.rb +23 -22
  177. data/spec/praxis/multipart/parser_spec.rb +7 -9
  178. data/spec/praxis/notifications_spec.rb +4 -4
  179. data/spec/praxis/plugin_concern_spec.rb +5 -6
  180. data/spec/praxis/renderer_spec.rb +10 -9
  181. data/spec/praxis/request_spec.rb +38 -41
  182. data/spec/praxis/request_stages/action_spec.rb +14 -15
  183. data/spec/praxis/request_stages/request_stage_spec.rb +30 -41
  184. data/spec/praxis/request_stages/validate_spec.rb +3 -1
  185. data/spec/praxis/response_definition_spec.rb +79 -92
  186. data/spec/praxis/response_spec.rb +28 -39
  187. data/spec/praxis/responses/internal_server_error_spec.rb +6 -9
  188. data/spec/praxis/responses/validation_error_spec.rb +17 -18
  189. data/spec/praxis/route_spec.rb +4 -7
  190. data/spec/praxis/router_spec.rb +69 -79
  191. data/spec/praxis/routing_config_spec.rb +15 -14
  192. data/spec/praxis/stage_spec.rb +56 -53
  193. data/spec/praxis/trait_spec.rb +17 -18
  194. data/spec/praxis/types/fuzzy_hash_spec.rb +11 -9
  195. data/spec/praxis/types/multipart_array/part_definition_spec.rb +3 -2
  196. data/spec/praxis/types/multipart_array_spec.rb +33 -48
  197. data/spec/spec_app/app/concerns/authenticated.rb +5 -5
  198. data/spec/spec_app/app/concerns/basic_api.rb +3 -1
  199. data/spec/spec_app/app/concerns/log_wrapper.rb +5 -3
  200. data/spec/spec_app/app/controllers/base_class.rb +6 -5
  201. data/spec/spec_app/app/controllers/instances.rb +31 -34
  202. data/spec/spec_app/app/controllers/volumes.rb +6 -6
  203. data/spec/spec_app/app/responses/multipart.rb +1 -2
  204. data/spec/spec_app/app/responses/other_response.rb +2 -2
  205. data/spec/spec_app/config/environment.rb +19 -6
  206. data/spec/spec_app/config.ru +4 -3
  207. data/spec/spec_app/design/api.rb +13 -15
  208. data/spec/spec_app/design/media_types/instance.rb +5 -5
  209. data/spec/spec_app/design/media_types/volume.rb +2 -1
  210. data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -1
  211. data/spec/spec_app/design/resources/instances.rb +9 -15
  212. data/spec/spec_app/design/resources/volume_snapshots.rb +4 -5
  213. data/spec/spec_app/design/resources/volumes.rb +4 -5
  214. data/spec/spec_helper.rb +11 -13
  215. data/spec/support/be_deep_equal_matcher.rb +5 -0
  216. data/spec/support/spec_authorization_plugin.rb +7 -12
  217. data/spec/support/spec_blueprints.rb +2 -1
  218. data/spec/support/spec_complex_authentication_plugin.rb +17 -34
  219. data/spec/support/spec_endpoint_definitions.rb +2 -3
  220. data/spec/support/spec_media_types.rb +28 -35
  221. data/spec/support/spec_resources.rb +20 -18
  222. data/spec/support/spec_simple_authentication_plugin.rb +5 -9
  223. data/tasks/loader.thor +4 -2
  224. data/tasks/thor/app.rb +7 -5
  225. data/tasks/thor/example.rb +23 -22
  226. data/tasks/thor/model.rb +7 -7
  227. data/tasks/thor/scaffold.rb +23 -23
  228. data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +0 -8
  229. data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +1 -2
  230. metadata +72 -84
  231. data/MAINTAINERS +0 -2
  232. data/TODO.md +0 -25
  233. data/spec/praxis/api_resource_spec.rb +0 -0
  234. data/spec/praxis/dispatcher_spec.rb +0 -0
  235. data/spec/spec_app/app/responses/bulk_response.rb +0 -0
@@ -1,20 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'Functional specs' do
4
-
5
6
  def app
6
7
  Praxis::Application.instance
7
8
  end
8
9
 
9
- let(:session) { double("session", valid?: true)}
10
+ let(:session) { double('session', valid?: true) }
10
11
 
11
12
  context 'index' do
12
-
13
13
  context 'with a valid request' do
14
14
  it 'is successful' do
15
15
  get '/api/clouds/1/instances?api_version=1.0', nil, 'global_session' => session
16
16
  expect(last_response.headers['Content-Type']).to(
17
- eq("application/vnd.acme.instance;type=collection"))
17
+ eq('application/vnd.acme.instance;type=collection')
18
+ )
18
19
  end
19
20
  end
20
21
 
@@ -59,7 +60,6 @@ describe 'Functional specs' do
59
60
  expect(response['summary']).to eq 'Error validating request data.'
60
61
  expect(response['errors']).to match_array([/.*cloud_id.*is smaller than the allowed min/])
61
62
  end
62
-
63
63
  end
64
64
 
65
65
  context 'with a header that is invalid' do
@@ -87,12 +87,12 @@ describe 'Functional specs' do
87
87
  end
88
88
 
89
89
  it 'fails to validate the response' do
90
- get '/api/clouds/1/instances?response_content_type=somejunk&api_version=1.0', nil, 'HTTP_FOO' => "bar", 'global_session' => session
90
+ get '/api/clouds/1/instances?response_content_type=somejunk&api_version=1.0', nil, 'HTTP_FOO' => 'bar', 'global_session' => session
91
91
  expect(last_response.status).to eq(400)
92
92
  response = JSON.parse(last_response.body)
93
93
 
94
94
  expect(response['name']).to eq('ValidationError')
95
- expect(response['summary']).to eq("Error validating response")
95
+ expect(response['summary']).to eq('Error validating response')
96
96
  expect(response['errors'].first).to match(/Bad Content-Type/)
97
97
  end
98
98
 
@@ -105,30 +105,29 @@ describe 'Functional specs' do
105
105
  end
106
106
 
107
107
  it 'fails to validate the response' do
108
- expect {
109
- get '/api/clouds/1/instances?response_content_type=somejunk&api_version=1.0',nil, 'global_session' => session
110
- }.to_not raise_error
108
+ expect do
109
+ get '/api/clouds/1/instances?response_content_type=somejunk&api_version=1.0', nil, 'global_session' => session
110
+ end.to_not raise_error
111
111
  end
112
-
113
112
  end
114
113
  end
115
-
116
114
  end
117
115
 
118
116
  it 'works' do
119
- the_body = StringIO.new("{}") # This is a funny, GET request expecting a body
120
- get '/api/clouds/1/instances/2?junk=foo&api_version=1.0', nil,'rack.input' => the_body,'CONTENT_TYPE' => "application/json", 'global_session' => session
117
+ the_body = StringIO.new('{}') # This is a funny, GET request expecting a body
118
+ get '/api/clouds/1/instances/2?junk=foo&api_version=1.0', nil, 'rack.input' => the_body, 'CONTENT_TYPE' => 'application/json', 'global_session' => session
121
119
  expect(last_response.status).to eq(200)
122
120
  expected = {
123
- "cloud_id" => 1,
124
- "id"=>2,
125
- "junk"=>"foo",
126
- "other_params"=>{
127
- "some_date"=>"2012-12-21T00:00:00+00:00",
128
- "fail_filter"=>false
121
+ 'cloud_id' => 1,
122
+ 'id' => 2,
123
+ 'junk' => 'foo',
124
+ 'other_params' => {
125
+ 'some_date' => '2012-12-21T00:00:00+00:00',
126
+ 'fail_filter' => false
129
127
  },
130
- "payload"=>{
131
- "optional"=>"not given"}
128
+ 'payload' => {
129
+ 'optional' => 'not given'
130
+ }
132
131
  }
133
132
 
134
133
  expect(JSON.parse(last_response.body)).to eq(expected)
@@ -144,9 +143,8 @@ describe 'Functional specs' do
144
143
  end
145
144
 
146
145
  context 'bulk_create multipart' do
147
-
148
146
  let(:instance) { Instance.example }
149
- let(:instance_json) { JSON.pretty_generate(instance.render(fields: {id: true, name: true})) }
147
+ let(:instance_json) { JSON.pretty_generate(instance.render(fields: { id: true, name: true })) }
150
148
 
151
149
  let(:form) do
152
150
  form_data = MIME::Multipart::FormData.new
@@ -170,15 +168,14 @@ describe 'Functional specs' do
170
168
 
171
169
  instance_headers = instance_part.headers
172
170
  expect(instance_headers['Status']).to eq('201')
173
- expect(instance_headers['Location']).to match(%r|/clouds/.*/instances/.*|)
171
+ expect(instance_headers['Location']).to match(%r{/clouds/.*/instances/.*})
174
172
 
175
173
  response_instance = JSON.parse(instance_part.body)
176
- expect(response_instance["key"]).to eq(instance.id)
177
- expect(response_instance["value"].values).to eq(instance.render(fields: {id: true, name: true}).values)
174
+ expect(response_instance['key']).to eq(instance.id)
175
+ expect(response_instance['value'].values).to eq(instance.render(fields: { id: true, name: true }).values)
178
176
  end
179
177
  end
180
178
 
181
-
182
179
  context 'attach_file' do
183
180
  let(:form) do
184
181
  form_data = MIME::Multipart::FormData.new
@@ -229,9 +226,8 @@ describe 'Functional specs' do
229
226
  response = JSON.parse(last_response.body)
230
227
 
231
228
  expect(response['name']).to eq('ValidationError')
232
- expect(response['errors']).to eq(["Attribute $.payload.destination_path is required"])
229
+ expect(response['errors']).to eq(['Attribute $.payload.destination_path is required'])
233
230
  end
234
-
235
231
  end
236
232
 
237
233
  context 'with an extra key in the form' do
@@ -257,28 +253,26 @@ describe 'Functional specs' do
257
253
  before do
258
254
  post '/api/clouds/1/instances/2/files?api_version=1.0', body, 'CONTENT_TYPE' => content_type, 'global_session' => session
259
255
  end
260
- its(:keys){ should eq(['destination_path','name','filename','type','contents','options'])}
261
- its(['options']){ should eq({"extra_thing"=>"I am extra"})}
256
+ its(:keys) { should eq(%w[destination_path name filename type contents options]) }
257
+ its(['options']) { should eq({ 'extra_thing' => 'I am extra' }) }
262
258
  end
263
-
264
259
  end
265
260
 
266
-
267
261
  context 'not found and API versions' do
268
262
  context 'when no version is specified' do
269
263
  it 'it tells you which available api versions would match' do
270
- get '/api/clouds/1/instances/2?junk=foo',nil, 'global_session' => session
264
+ get '/api/clouds/1/instances/2?junk=foo', nil, 'global_session' => session
271
265
 
272
266
  expect(last_response.status).to eq(404)
273
- expect(last_response.headers["Content-Type"]).to eq("text/plain")
274
- expect(last_response.body).to eq("NotFound. Your request did not specify an API version. Available versions = \"1.0\".")
267
+ expect(last_response.headers['Content-Type']).to eq('text/plain')
268
+ expect(last_response.body).to eq('NotFound. Your request did not specify an API version. Available versions = "1.0".')
275
269
  end
276
270
  it 'it just gives you a simple not found when nothing would have matched' do
277
271
  get '/foobar?junk=foo', nil, 'global_session' => session
278
272
 
279
273
  expect(last_response.status).to eq(404)
280
- expect(last_response.headers["Content-Type"]).to eq("text/plain")
281
- expect(last_response.body).to eq("NotFound")
274
+ expect(last_response.headers['Content-Type']).to eq('text/plain')
275
+ expect(last_response.body).to eq('NotFound')
282
276
  end
283
277
  end
284
278
 
@@ -287,11 +281,10 @@ describe 'Functional specs' do
287
281
  get '/api/clouds/1/instances/2?junk=foo&api_version=50.0', nil, 'global_session' => session
288
282
 
289
283
  expect(last_response.status).to eq(404)
290
- expect(last_response.headers["Content-Type"]).to eq("text/plain")
291
- expect(last_response.body).to eq("NotFound. Your request specified API version = \"50.0\". Available versions = \"1.0\".")
284
+ expect(last_response.headers['Content-Type']).to eq('text/plain')
285
+ expect(last_response.body).to eq('NotFound. Your request specified API version = "50.0". Available versions = "1.0".')
292
286
  end
293
287
  end
294
-
295
288
  end
296
289
 
297
290
  context 'volumes' do
@@ -304,7 +297,7 @@ describe 'Functional specs' do
304
297
  get '/api/clouds/1/volumes/123?junk=stuff', nil, 'global_session' => session
305
298
  expect(last_response.status).to eq(200)
306
299
  expect(Volume.load(last_response.body).validate).to be_empty
307
- expect(last_response.headers["Content-Type"]).to eq("application/vnd.acme.volume")
300
+ expect(last_response.headers['Content-Type']).to eq('application/vnd.acme.volume')
308
301
  end
309
302
  end
310
303
  context 'when an authorization header is passed' do
@@ -317,7 +310,6 @@ describe 'Functional specs' do
317
310
  get '/api/clouds/1/volumes/123?junk=stuff', nil, 'HTTP_AUTHORIZATION' => 'the secret', 'global_session' => session
318
311
  expect(last_response.status).to eq(200)
319
312
  end
320
-
321
313
  end
322
314
 
323
315
  context 'index action with no args defined' do
@@ -329,7 +321,7 @@ describe 'Functional specs' do
329
321
  end
330
322
 
331
323
  context 'wildcard verb routing' do
332
- let(:content_type){ 'application/json' }
324
+ let(:content_type) { 'application/json' }
333
325
  it 'can terminate instances with POST' do
334
326
  post '/api/clouds/23/instances/1/terminate?api_version=1.0', nil, 'CONTENT_TYPE' => content_type, 'global_session' => session
335
327
  expect(last_response.status).to eq(200)
@@ -338,7 +330,6 @@ describe 'Functional specs' do
338
330
  post '/api/clouds/23/instances/1/terminate?api_version=1.0', nil, 'CONTENT_TYPE' => content_type, 'global_session' => session
339
331
  expect(last_response.status).to eq(200)
340
332
  end
341
-
342
333
  end
343
334
 
344
335
  context 'route options' do
@@ -381,7 +372,6 @@ describe 'Functional specs' do
381
372
  end
382
373
 
383
374
  context 'update' do
384
-
385
375
  let(:body) { JSON.pretty_generate(request_payload) }
386
376
  let(:content_type) { 'application/json' }
387
377
 
@@ -399,19 +389,19 @@ describe 'Functional specs' do
399
389
  end
400
390
 
401
391
  context 'with a provided name' do
402
- let(:request_payload) { {name: 'MyInstance'} }
392
+ let(:request_payload) { { name: 'MyInstance' } }
403
393
  its(['name']) { should eq('MyInstance') }
404
394
  it { should_not have_key('root_volume') }
405
395
  end
406
396
 
407
397
  context 'with an explicitly-nil root_volme' do
408
- let(:request_payload) { {name: 'MyInstance', root_volume: nil} }
398
+ let(:request_payload) { { name: 'MyInstance', root_volume: nil } }
409
399
  its(['name']) { should eq('MyInstance') }
410
400
  its(['root_volume']) { should be(nil) }
411
401
  end
412
402
 
413
403
  context 'with an invalid name' do
414
- let(:request_payload) { {name: 'Invalid Name'} }
404
+ let(:request_payload) { { name: 'Invalid Name' } }
415
405
 
416
406
  its(['name']) { should eq 'ValidationError' }
417
407
  its(['summary']) { should eq 'Error validating response' }
@@ -421,7 +411,5 @@ describe 'Functional specs' do
421
411
  expect(last_response.status).to eq(400)
422
412
  end
423
413
  end
424
-
425
414
  end
426
-
427
415
  end
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe Praxis::ActionDefinition do
4
- class SpecMediaType < Praxis::MediaType
5
- identifier 'application/json'
5
+ class SpecMediaType < Praxis::MediaType
6
+ identifier 'application/json'
6
7
 
7
- attributes do
8
- attribute :one, String
9
- attribute :two, Integer
10
- end
11
- default_fieldset do
12
- attribute :one
13
- end
8
+ attributes do
9
+ attribute :one, String
10
+ attribute :two, Integer
11
+ end
12
+ default_fieldset do
13
+ attribute :one
14
14
  end
15
+ end
15
16
 
17
+ describe Praxis::ActionDefinition do
16
18
  let(:endpoint_definition) do
17
19
  Class.new do
18
20
  include Praxis::EndpointDefinition
@@ -26,20 +28,20 @@ describe Praxis::ActionDefinition do
26
28
  prefix '/foobars/hello_world'
27
29
  action_defaults do
28
30
  payload { attribute :inherited, String }
29
- headers { header "Inherited", String }
31
+ headers { header 'Inherited', String }
30
32
  params { attribute :inherited, String }
31
33
  end
32
34
  end
33
35
  end
34
36
 
35
37
  subject(:action) do
36
-
37
38
  Praxis::ApiDefinition.define do |api|
38
- api.response_template :ok do |media_type: , location: nil, headers: nil, description: nil |
39
+ api.response_template :ok do |media_type:, location: nil, headers: nil, description: nil|
39
40
  status 200
40
41
 
41
42
  media_type media_type
42
43
  location location
44
+ description description
43
45
  headers&.each do |(name, value)|
44
46
  header(name, value)
45
47
  end
@@ -48,9 +50,9 @@ describe Praxis::ActionDefinition do
48
50
  Praxis::ActionDefinition.new(:foo, endpoint_definition) do
49
51
  routing { get '/:one' }
50
52
  payload { attribute :two, String }
51
- headers { header "X_REQUESTED_WITH", 'XMLHttpRequest' }
53
+ headers { header 'X_REQUESTED_WITH', 'XMLHttpRequest' }
52
54
  params { attribute :one, String }
53
- response :ok, headers: { "Foo" => "Bar"}, location: %r{/some/thing}
55
+ response :ok, headers: { 'Foo' => 'Bar' }, location: %r{/some/thing}
54
56
  end
55
57
  end
56
58
 
@@ -61,8 +63,8 @@ describe Praxis::ActionDefinition do
61
63
  its('params.attributes') { should have_key :inherited }
62
64
  its('payload.attributes') { should have_key :two }
63
65
  its('payload.attributes') { should have_key :inherited }
64
- its('headers.attributes') { should have_key "X_REQUESTED_WITH" }
65
- its('headers.attributes') { should have_key "Inherited" }
66
+ its('headers.attributes') { should have_key 'X_REQUESTED_WITH' }
67
+ its('headers.attributes') { should have_key 'Inherited' }
66
68
  its('metadata') { should_not have_key :doc_visibility }
67
69
  end
68
70
 
@@ -99,23 +101,21 @@ describe Praxis::ActionDefinition do
99
101
  attribute :app_name, String
100
102
  attribute :name, String
101
103
  end
102
-
103
104
  end
104
105
  end
105
- let(:traits) { {test: trait} }
106
+ let(:traits) { { test: trait } }
106
107
 
107
108
  before do
108
109
  allow(Praxis::ApiDefinition.instance).to receive(:traits).and_return(traits)
109
110
  end
110
111
 
111
- its('params.attributes.keys') { should eq [:inherited, :app_name, :name, :one]}
112
+ its('params.attributes.keys') { should eq %i[inherited app_name name one] }
112
113
  its('route.path.to_s') { should eq '/api/foobars/hello_world/test_trait/:app_name/:one' }
113
114
  its(:traits) { should eq [:test] }
114
115
 
115
116
  it 'is reflected in the describe output' do
116
117
  expect(action.describe[:traits]).to eq [:test]
117
118
  end
118
-
119
119
  end
120
120
 
121
121
  describe '#params' do
@@ -129,7 +129,7 @@ describe Praxis::ActionDefinition do
129
129
  end
130
130
 
131
131
  attributes = subject.params.attributes.keys
132
- expect(attributes).to match_array([:one, :inherited, :more])
132
+ expect(attributes).to match_array(%i[one inherited more])
133
133
  end
134
134
 
135
135
  it 'merges options (which allows overriding)' do
@@ -144,19 +144,18 @@ describe Praxis::ActionDefinition do
144
144
  before do
145
145
  action.params do
146
146
  attribute :two
147
- #requires.at_most(1).of :one, :two
147
+ # requires.at_most(1).of :one, :two
148
148
  requires :one
149
149
  end
150
150
  end
151
151
 
152
- let(:value) { {two: 2} }
152
+ let(:value) { { two: 2 } }
153
153
  it 'includes the requirements in the param struct type' do
154
154
  errors = action.params.load(value).validate
155
155
  expect(errors).to have(1).item
156
156
  expect(errors.first).to match('Attribute $.key(:one) is required.')
157
157
  end
158
158
  end
159
-
160
159
  end
161
160
 
162
161
  describe '#payload' do
@@ -165,15 +164,14 @@ describe Praxis::ActionDefinition do
165
164
  expect(subject.payload.options[:null]).to be(false)
166
165
  end
167
166
 
168
-
169
167
  it 'merges in more payload' do
170
168
  subject.payload do
171
169
  attribute :more, Attributor::Integer
172
170
  end
173
171
 
174
- expect(subject.payload.attributes.keys).to match_array([
175
- :two, :inherited, :more
176
- ])
172
+ expect(subject.payload.attributes.keys).to match_array(%i[
173
+ two inherited more
174
+ ])
177
175
  end
178
176
 
179
177
  it 'merges options (which allows overriding)' do
@@ -200,10 +198,10 @@ describe Praxis::ActionDefinition do
200
198
 
201
199
  it 'merges in more headers' do
202
200
  subject.headers do
203
- header "more"
201
+ header 'more'
204
202
  end
205
203
 
206
- expected_array = ["X_REQUESTED_WITH", "Inherited", "more"]
204
+ expected_array = %w[X_REQUESTED_WITH Inherited more]
207
205
  expect(subject.headers.attributes.keys).to match_array(expected_array)
208
206
  end
209
207
 
@@ -211,7 +209,7 @@ describe Praxis::ActionDefinition do
211
209
  expect(subject.headers.options[:required]).to be(true)
212
210
 
213
211
  subject.headers required: false do
214
- header "even_more"
212
+ header 'even_more'
215
213
  end
216
214
 
217
215
  expect(subject.headers.options[:required]).to be(false)
@@ -229,7 +227,7 @@ describe Praxis::ActionDefinition do
229
227
  expect(action.route.path.to_s).to eq '/api/clouds/:cloud_id/volumes/:volume_id/snapshots/:id'
230
228
  end
231
229
 
232
- its('params.attributes'){ should have_key(:cloud_id) }
230
+ its('params.attributes') { should have_key(:cloud_id) }
233
231
 
234
232
  context 'with pre-existing parent param' do
235
233
  let(:action) { resource.actions[:index] }
@@ -242,7 +240,6 @@ describe Praxis::ActionDefinition do
242
240
  it { should_not be nil }
243
241
  its(:options) { should eq parent_param.options }
244
242
  end
245
-
246
243
  end
247
244
  end
248
245
 
@@ -277,9 +274,8 @@ describe Praxis::ActionDefinition do
277
274
 
278
275
  it 'works' do
279
276
  expansion = action.route.path.expand(cloud_id: '232', id: '2')
280
- expect(expansion).to eq "/api/clouds/232/instances/2"
277
+ expect(expansion).to eq '/api/clouds/232/instances/2'
281
278
  end
282
-
283
279
  end
284
280
 
285
281
  context 'with nodoc!' do
@@ -294,16 +290,14 @@ describe Praxis::ActionDefinition do
294
290
  it 'is exposed by describe' do
295
291
  expect(action.describe[:metadata][:doc_visibility]).to be(:none)
296
292
  end
297
-
298
293
  end
299
294
 
300
295
  context 'with a base_path and base_params on ApiDefinition' do
301
296
  # Without getting a fresh new ApiDefinition it is very difficult to test stuff using the Singleton
302
297
  # So for some tests we're gonna create a new instance and work with it to avoid the singleton issues
303
298
  let(:non_singleton_api) do
304
- api_def=Praxis::ApiDefinition.__send__(:new)
299
+ api_def = Praxis::ApiDefinition.__send__(:new)
305
300
  api_def.instance_eval do |api|
306
-
307
301
  api.info do
308
302
  base_path '/apps/:app_name'
309
303
  end
@@ -313,7 +307,6 @@ describe Praxis::ActionDefinition do
313
307
  attribute :app_name, String
314
308
  end
315
309
  end
316
-
317
310
  end
318
311
  api_def
319
312
  end
@@ -323,10 +316,9 @@ describe Praxis::ActionDefinition do
323
316
  end
324
317
 
325
318
  its('route.path.to_s') { should eq '/apps/:app_name/foobars/hello_world/:one' }
326
- its('params.attributes.keys') { should match_array [:inherited, :app_name, :one]}
319
+ its('params.attributes.keys') { should match_array %i[inherited app_name one] }
327
320
 
328
321
  context 'where the action overrides a base_param' do
329
-
330
322
  let(:endpoint_definition) do
331
323
  Class.new do
332
324
  include Praxis::EndpointDefinition
@@ -338,7 +330,7 @@ describe Praxis::ActionDefinition do
338
330
  prefix '/foobars/hello_world'
339
331
  action_defaults do
340
332
  payload { attribute :inherited, String }
341
- headers { header "Inherited", String }
333
+ headers { header 'Inherited', String }
342
334
  end
343
335
  end
344
336
  end
@@ -352,13 +344,11 @@ describe Praxis::ActionDefinition do
352
344
 
353
345
  subject(:attributes) { action.params.attributes }
354
346
 
355
- its(:keys) { should eq [:app_name]}
347
+ its(:keys) { should eq [:app_name] }
356
348
 
357
349
  it 'overrides the base param' do
358
350
  expect(attributes[:app_name].type).to eq(Attributor::Integer)
359
351
  end
360
-
361
352
  end
362
-
363
353
  end
364
354
  end