praxis 2.0.pre.17 → 2.0.pre.21

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 (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 +19 -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 +65 -95
  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 +80 -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 +11 -14
  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 +7 -4
  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 +61 -29
  45. data/lib/praxis/docs/open_api/server_object.rb +5 -2
  46. data/lib/praxis/docs/open_api/tag_object.rb +9 -6
  47. data/lib/praxis/docs/open_api_generator.rb +114 -150
  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 +196 -181
  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 +48 -44
  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 -22
  113. data/lib/praxis/request_stages/validate_payload.rb +25 -28
  114. data/lib/praxis/request_superclassing.rb +3 -3
  115. data/lib/praxis/resource_definition.rb +1 -0
  116. data/lib/praxis/response.rb +24 -26
  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 +17 -16
  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 +100 -115
  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 +44 -56
  145. data/spec/praxis/action_definition_spec.rb +39 -48
  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 +39 -29
  173. data/spec/praxis/mapper/selector_generator_spec.rb +80 -46
  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 +35 -40
  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 -17
  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 +6 -6
  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 +11 -17
  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 +5 -4
  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 +22 -16
  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,9 +1,9 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'spec_helper'
3
4
 
4
5
  describe Praxis::Responses::ValidationError do
5
-
6
- let(:summary){ "Something happened here" }
6
+ let(:summary) { 'Something happened here' }
7
7
  context 'a basic response' do
8
8
  subject(:response) { Praxis::Responses::ValidationError.new(summary: summary) }
9
9
  it 'always sets the json content type' do
@@ -18,10 +18,10 @@ describe Praxis::Responses::ValidationError do
18
18
  end
19
19
 
20
20
  context '.format!' do
21
- let(:errors) { [1,2] }
22
- let(:cause){ Exception.new( "cause message") }
23
- let(:exception_message){ "exception message" }
24
- let(:exception){ nil }
21
+ let(:errors) { [1, 2] }
22
+ let(:cause) { Exception.new('cause message') }
23
+ let(:exception_message) { 'exception message' }
24
+ let(:exception) { nil }
25
25
  subject(:response) { Praxis::Responses::ValidationError.new(summary: summary, errors: errors, exception: exception) }
26
26
  before do
27
27
  expect(response.body).to be_nil
@@ -29,18 +29,18 @@ describe Praxis::Responses::ValidationError do
29
29
  context 'when errors' do
30
30
  it 'it fills the errors key' do
31
31
  response.format!
32
- expect(response.body).to eq({name: 'ValidationError', summary: summary, errors: errors})
32
+ expect(response.body).to eq({ name: 'ValidationError', summary: summary, errors: errors })
33
33
  end
34
34
  end
35
35
 
36
36
  context 'without errors but with an exception' do
37
37
  let(:errors) { nil }
38
- let(:exception){ double("exception", message: exception_message, cause: cause)}
38
+ let(:exception) { double('exception', message: exception_message, cause: cause) }
39
39
  before do
40
- response.format!
41
- expect(response.body.keys).to include(:name,:summary)
42
- expect(response.body[:name]).to eq('ValidationError')
43
- expect(response.body[:summary]).to eq(summary)
40
+ response.format!
41
+ expect(response.body.keys).to include(:name, :summary)
42
+ expect(response.body[:name]).to eq('ValidationError')
43
+ expect(response.body[:summary]).to eq(summary)
44
44
  end
45
45
 
46
46
  context 'that has a message' do
@@ -51,14 +51,14 @@ describe Praxis::Responses::ValidationError do
51
51
  end
52
52
 
53
53
  context 'that does not contain a message' do
54
- let(:exception_message){ nil }
54
+ let(:exception_message) { nil }
55
55
  it 'does not touch the errors key' do
56
56
  expect(response.body).to_not have_key(:errors)
57
57
  end
58
58
  end
59
59
 
60
60
  context 'without cause' do
61
- let(:cause){ nil}
61
+ let(:cause) { nil }
62
62
  it 'does not include it in the output' do
63
63
  expect(response.body).to_not have_key(:cause)
64
64
  end
@@ -67,15 +67,14 @@ describe Praxis::Responses::ValidationError do
67
67
  context 'with a cause' do
68
68
  it 'it fills the cause too' do
69
69
  expect(response.body).to have_key(:cause)
70
- expect(response.body[:cause]).to eq({name: cause.class.name, message: cause.message })
70
+ expect(response.body[:cause]).to eq({ name: cause.class.name, message: cause.message })
71
71
  end
72
72
  end
73
73
  end
74
-
75
74
  end
76
75
 
77
76
  context 'its response template' do
78
- let(:template){ Praxis::ApiDefinition.instance.responses[:validation_error] }
77
+ let(:template) { Praxis::ApiDefinition.instance.responses[:validation_error] }
79
78
  it 'is registered with the ApiDefinition' do
80
79
  expect(template).to be_kind_of(Praxis::ResponseTemplate)
81
80
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::Route do
4
-
5
6
  let(:verb) { 'GET' }
6
7
  let(:path) { '/base/stuff' }
7
8
  let(:prefixed_path) { '/stuff' }
@@ -23,15 +24,11 @@ describe Praxis::Route do
23
24
 
24
25
  context '#describe' do
25
26
  subject(:description) { route.describe }
26
- it { should eq({verb:verb, path:path , version:version}) }
27
+ it { should eq({ verb: verb, path: path, version: version }) }
27
28
 
28
29
  context 'with options' do
29
- let(:options) { {option: 'value'} }
30
+ let(:options) { { option: 'value' } }
30
31
  its([:options]) { should eq(options) }
31
32
  end
32
-
33
33
  end
34
-
35
-
36
-
37
34
  end
@@ -1,26 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::Router do
4
6
  describe Praxis::Router::VersionMatcher do
5
- let(:endpoint_definition){ double("endpoint_definition", version_options: { using: [:header, :params] }) }
6
- let(:action){ double("action", endpoint_definition: endpoint_definition ) }
7
- let(:target){ double("target", action: action ) }
8
- let(:args){ {version: "1.0"} }
9
- subject(:matcher){ Praxis::Router::VersionMatcher.new(target,**args) }
7
+ let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) }
8
+ let(:action) { double('action', endpoint_definition: endpoint_definition) }
9
+ let(:target) { double('target', action: action) }
10
+ let(:args) { { version: '1.0' } }
11
+ subject(:matcher) { Praxis::Router::VersionMatcher.new(target, **args) }
10
12
 
11
13
  context '.initialize' do
12
- let(:args){ {} }
14
+ let(:args) { {} }
13
15
  it 'defaults to no version' do
14
- expect( matcher.instance_variable_get(:@version) ).to eq("n/a")
16
+ expect(matcher.instance_variable_get(:@version)).to eq('n/a')
15
17
  end
16
18
  end
17
19
 
18
20
  context '.call' do
19
- let(:env){ {"HTTP_X_API_VERSION" => request_version } }
20
- let(:request) {Praxis::Request.new(env)}
21
+ let(:env) { { 'HTTP_X_API_VERSION' => request_version } }
22
+ let(:request) { Praxis::Request.new(env) }
21
23
 
22
24
  context 'with matching versions' do
23
- let(:request_version) { "1.0" }
25
+ let(:request_version) { '1.0' }
24
26
  it 'calls the target' do
25
27
  expect(target).to receive(:call).with(request)
26
28
  matcher.call(request)
@@ -28,67 +30,63 @@ describe Praxis::Router do
28
30
  end
29
31
 
30
32
  context 'with non-matching versions' do
31
- let(:request_version) { "4.0" }
33
+ let(:request_version) { '4.0' }
32
34
  before do
33
35
  expect { matcher.call(request) }.to throw_symbol(:pass)
34
36
  end
35
37
  it 'does not call the target' do
36
- expect( target ).not_to receive(:call).with(request)
38
+ expect(target).not_to receive(:call).with(request)
37
39
  end
38
40
  it 'saves the unmatched version' do
39
- expect( request.unmatched_versions ).to include(args[:version])
41
+ expect(request.unmatched_versions).to include(args[:version])
40
42
  end
41
43
  end
42
-
43
44
  end
44
45
  end
45
46
 
46
47
  describe Praxis::Router::RequestRouter do
48
+ let(:request) { double('request', route_params: '', path: 'path') }
49
+ let(:callback) { double('callback') }
47
50
 
48
- let(:request) {double("request", route_params: '', path: 'path')}
49
- let(:callback) {double("callback")}
51
+ subject(:request_router) { Praxis::Router::RequestRouter.new }
50
52
 
51
- subject(:request_router) {Praxis::Router::RequestRouter.new}
52
-
53
- context ".invoke" do
54
- it "update request and call request for callback" do
53
+ context '.invoke' do
54
+ it 'update request and call request for callback' do
55
55
  allow(request).to receive(:route_params=)
56
56
  allow(callback).to receive(:call).and_return(1)
57
57
 
58
- invoke_call = request_router.invoke(callback, request, "params", "pattern")
58
+ invoke_call = request_router.invoke(callback, request, 'params', 'pattern')
59
59
  expect(invoke_call).to eq(1)
60
60
  end
61
61
  end
62
62
 
63
- context ".string_for" do
64
- it "returns request path string" do
63
+ context '.string_for' do
64
+ it 'returns request path string' do
65
65
  expect(request_router.string_for(request)).to eq('path')
66
66
  end
67
67
  end
68
68
  end
69
69
 
70
- let(:application) { instance_double('Praxis::Application')}
71
- subject(:router) {Praxis::Router.new(application)}
70
+ let(:application) { instance_double('Praxis::Application') }
71
+ subject(:router) { Praxis::Router.new(application) }
72
72
 
73
- context "attributes" do
74
- its(:request_class) {should be(Praxis::Request)}
73
+ context 'attributes' do
74
+ its(:request_class) { should be(Praxis::Request) }
75
75
  end
76
76
 
77
- context ".add_route" do
78
-
79
- let(:route){ double('route', options: [1], version: 1, verb: 'verb', path: 'path')}
80
- let(:target){ double('target') }
81
- let(:verb_router){ double('verb_router') }
77
+ context '.add_route' do
78
+ let(:route) { double('route', options: [1], version: 1, verb: 'verb', path: 'path') }
79
+ let(:target) { double('target') }
80
+ let(:verb_router) { double('verb_router') }
82
81
 
83
- let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) }
82
+ let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) }
84
83
  let(:action) { double('action', endpoint_definition: endpoint_definition) }
85
84
  let(:target) { double('target', action: action) }
86
85
 
87
-
88
86
  context 'with params or header versioning' do
89
87
  it 'wraps the target with a VersionMatcher' do
90
- router.instance_variable_set( :@routes, {'verb'=>verb_router} ) # Ugly, but no need to have a reader
91
- expect(verb_router).to receive(:on) do|path, args|# .with(route.path, call: "foo")
88
+ router.instance_variable_set(:@routes, { 'verb' => verb_router }) # Ugly, but no need to have a reader
89
+ expect(verb_router).to receive(:on) do |path, args| # .with(route.path, call: "foo")
92
90
  expect(path).to eq(route.path)
93
91
  expect(args).to be_kind_of(Hash)
94
92
  expect(args[:call]).to be_kind_of(Praxis::Router::VersionMatcher)
@@ -96,75 +94,72 @@ describe Praxis::Router do
96
94
  router.add_route(target, route)
97
95
  end
98
96
  end
99
-
100
97
  end
101
98
 
102
- context ".call" do
103
- let(:env){ {"PATH_INFO"=>request_path_info, "REQUEST_METHOD"=>request_verb} }
99
+ context '.call' do
100
+ let(:env) { { 'PATH_INFO' => request_path_info, 'REQUEST_METHOD' => request_verb } }
104
101
  let(:request_verb) { 'POST' }
105
102
  let(:request_path_info) { '/' }
106
- let(:request_version){ nil }
107
- let(:request) {Praxis::Request.new(env)}
108
- let(:router_response){ 1 }
109
- let(:router_response_for_post){ "POST result" }
110
- let(:router_response_for_wildcard){ "* result" }
111
- let(:post_target_router){ double("POST target", call: router_response_for_post) }
112
- let(:any_target_router){ double("ANY target", call: router_response_for_wildcard) }
113
-
114
- let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) }
103
+ let(:request_version) { nil }
104
+ let(:request) { Praxis::Request.new(env) }
105
+ let(:router_response) { 1 }
106
+ let(:router_response_for_post) { 'POST result' }
107
+ let(:router_response_for_wildcard) { '* result' }
108
+ let(:post_target_router) { double('POST target', call: router_response_for_post) }
109
+ let(:any_target_router) { double('ANY target', call: router_response_for_wildcard) }
110
+
111
+ let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) }
115
112
  let(:action) { double('action', endpoint_definition: endpoint_definition) }
116
113
  let(:target) { double('target', action: action) }
117
114
 
118
115
  before do
119
116
  env['HTTP_X_API_VERSION'] = request_version if request_version
120
- allow_any_instance_of(Praxis::Router::RequestRouter).
121
- to receive(:call).with(request).and_return(router_response)
122
- router.add_route(target,double("route1", verb: 'POST', path: '/', options: {} , version: request_version))
117
+ allow_any_instance_of(Praxis::Router::RequestRouter)
118
+ .to receive(:call).with(request).and_return(router_response)
119
+ router.add_route(target, double('route1', verb: 'POST', path: '/', options: {}, version: request_version))
123
120
  # Hijack the callable block in the routes (since there's no way to point back to the registered route object)
124
121
  router.instance_variable_get(:@routes)['POST'] = post_target_router
125
-
126
122
  end
127
123
 
128
124
  context 'for routes without wildcards (a single POST route)' do
129
-
130
125
  context 'and an incoming POST request' do
131
- it "finds a match and invokes it the route" do
126
+ it 'finds a match and invokes it the route' do
132
127
  expect(router.call(request)).to eq(router_response_for_post)
133
128
  end
134
129
  end
135
130
  context 'and an incoming PUT request' do
136
131
  let(:request_verb) { 'PUT' }
137
- it "does not find a route" do
138
- response_code, _ , _ = router.call(request)
132
+ it 'does not find a route' do
133
+ response_code, = router.call(request)
139
134
  expect(response_code).to be(404)
140
135
  end
141
136
  end
142
137
  end
143
138
 
144
139
  context 'for routes with wildcards (a POST and a * route)' do
145
- let(:endpoint_definition) { double('endpoint_definition', version_options: {using: [:header, :params]} ) }
140
+ let(:endpoint_definition) { double('endpoint_definition', version_options: { using: %i[header params] }) }
146
141
  let(:action) { double('action', endpoint_definition: endpoint_definition) }
147
142
  let(:target) { double('target', action: action) }
148
143
 
149
144
  before do
150
- router.add_route(target,double("route2", verb: 'ANY', path: '/*', options: {} , version: request_version))
145
+ router.add_route(target, double('route2', verb: 'ANY', path: '/*', options: {}, version: request_version))
151
146
  # Hijack the callable block in the routes (since there's no way to point back to the registered route object)
152
- router.instance_variable_get( :@routes )['ANY'] = any_target_router
147
+ router.instance_variable_get(:@routes)['ANY'] = any_target_router
153
148
  end
154
149
 
155
150
  context 'and an incoming PUT request' do
156
151
  let(:request_verb) { 'PUT' }
157
- it "it can successfully find a match using the wildcard target" do
152
+ it 'it can successfully find a match using the wildcard target' do
158
153
  expect(router.call(request)).to eq(router_response_for_wildcard)
159
154
  end
160
155
  end
161
156
  context 'and an incoming POST request' do
162
- it 'matches the most specific POST route, rather than the wildcard'do
157
+ it 'matches the most specific POST route, rather than the wildcard' do
163
158
  expect(router.call(request)).to eq(router_response_for_post)
164
159
  end
165
160
  end
166
161
  context 'and an incoming POST request (but that does not match other route conditions)' do
167
- let(:router_response_for_post){ :not_found }
162
+ let(:router_response_for_post) { :not_found }
168
163
  it 'still matches wildcard verb if that was route conditions-compatible' do
169
164
  expect(post_target_router).to receive(:call).once # try the match cause it's a POST
170
165
  expect(any_target_router).to receive(:call).once # fallback to wildcard upon a not_found
@@ -173,13 +168,12 @@ describe Praxis::Router do
173
168
  end
174
169
  end
175
170
 
176
- context "when not_found is returned" do
171
+ context 'when not_found is returned' do
177
172
  let(:request_verb) { 'DELETE' }
178
- let(:router_response){ :not_found }
179
-
173
+ let(:router_response) { :not_found }
180
174
 
181
175
  it 'sets X-Cascade: pass by default' do
182
- _, headers, _ = router.call(request)
176
+ _, headers, = router.call(request)
183
177
  expect(headers).to have_key('X-Cascade')
184
178
  expect(headers['X-Cascade']).to eq('pass')
185
179
  end
@@ -191,10 +185,9 @@ describe Praxis::Router do
191
185
  end
192
186
 
193
187
  it 'does not set X-Cascade: pass' do
194
- _, headers, _ = router.call(request)
195
- expect(headers).to_not have_key("X-Cascade")
188
+ _, headers, = router.call(request)
189
+ expect(headers).to_not have_key('X-Cascade')
196
190
  end
197
-
198
191
  end
199
192
 
200
193
  context 'with versioning' do
@@ -202,29 +195,28 @@ describe Praxis::Router do
202
195
  request.instance_variable_set(:@unmatched_versions, unmatched_versions)
203
196
  end
204
197
 
205
- context "having passed no version in the request" do
198
+ context 'having passed no version in the request' do
206
199
  context 'and no controllers matching the path' do
207
200
  let(:unmatched_versions) { Set.new([]) }
208
201
 
209
202
  it 'returns a basic "NotFound" response: 404 status, text/plain content and "NotFound" body' do
210
- expect( router.call(request) ).to eq([404, {"Content-Type" => "text/plain","X-Cascade"=>"pass"}, ["NotFound"]])
203
+ expect(router.call(request)).to eq([404, { 'Content-Type' => 'text/plain', 'X-Cascade' => 'pass' }, ['NotFound']])
211
204
  end
212
205
  end
213
206
 
214
207
  context 'and some controllers matching the path' do
215
- let(:unmatched_versions) { Set.new(["1.0"]) }
208
+ let(:unmatched_versions) { Set.new(['1.0']) }
216
209
  it 'returns a specific body response noting which request versions would matched if passed in' do
217
210
  _, _, body = router.call(request)
218
- expect( body.first ).to eq('NotFound. Your request did not specify an API version. Available versions = "1.0".')
211
+ expect(body.first).to eq('NotFound. Your request did not specify an API version. Available versions = "1.0".')
219
212
  end
220
213
  end
221
214
  end
222
215
 
223
- context "having passed a version in the request" do
224
-
216
+ context 'having passed a version in the request' do
225
217
  context 'but having no controllers matching the path part' do
226
- let(:request_version) { "50.0" }
227
- let(:unmatched_versions) { Set.new(["1.0","2.0"]) }
218
+ let(:request_version) { '50.0' }
219
+ let(:unmatched_versions) { Set.new(['1.0', '2.0']) }
228
220
 
229
221
  it 'returns a specific body response noting that the version might be wrong (and which could be right)' do
230
222
  code, headers, body = router.call(request)
@@ -235,8 +227,6 @@ describe Praxis::Router do
235
227
  end
236
228
  end
237
229
  end
238
-
239
-
240
230
  end
241
231
  end
242
232
  end
@@ -1,22 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::RoutingConfig do
4
-
5
6
  let(:endpoint_definition) do
6
7
  Class.new do
7
8
  include Praxis::EndpointDefinition
8
- def self.name; 'MyResource'; end
9
+ def self.name
10
+ 'MyResource'
11
+ end
9
12
  end
10
13
  end
11
14
 
12
- let(:routing_block) { Proc.new{} }
13
- let(:base_path){ '' }
14
- let(:default_route_prefix) { "/" + endpoint_definition.name.split("::").last.underscore }
15
+ let(:routing_block) { proc {} }
16
+ let(:base_path) { '' }
17
+ let(:default_route_prefix) { "/#{endpoint_definition.name.split('::').last.underscore}" }
15
18
 
16
- subject(:routing_config){ Praxis::RoutingConfig.new(base: base_path, &routing_block) }
19
+ subject(:routing_config) { Praxis::RoutingConfig.new(base: base_path, &routing_block) }
17
20
 
18
21
  its(:version) { should eq('n/a') }
19
- its(:prefix ) { should eq('') }
22
+ its(:prefix) { should eq('') }
20
23
 
21
24
  context '#prefix' do
22
25
  it 'sets the prefix' do
@@ -35,15 +38,14 @@ describe Praxis::RoutingConfig do
35
38
  routing_config.prefix '/people'
36
39
  expect(routing_config.prefix).to eq('/people')
37
40
  end
38
-
39
41
  end
40
42
 
41
43
  context '#add_route' do
42
44
  let(:path) { '/people' }
43
45
  let(:options) { {} }
44
- let(:base_path){ '/api' }
45
- let(:route) { routing_config.add_route 'GET', path, **options}
46
-
46
+ let(:base_path) { '/api' }
47
+ let(:route) { routing_config.add_route 'GET', path, **options }
48
+
47
49
  it 'returns a corresponding Praxis::Route' do
48
50
  expect(route).to be_kind_of(Praxis::Route)
49
51
  end
@@ -53,11 +55,11 @@ describe Praxis::RoutingConfig do
53
55
  end
54
56
 
55
57
  context 'passing options' do
56
- let(:options){ { except: '/special' } }
58
+ let(:options) { { except: '/special' } }
57
59
 
58
60
  it 'passes them through the underlying mustermann object (telling it to ignore unknown ones)' do
59
61
  expect(Mustermann).to receive(:new).with(base_path + path, hash_including(ignore_unknown_options: true, except: '/special'))
60
- expect(route.options).to eq( { except: '/special' })
62
+ expect(route.options).to eq({ except: '/special' })
61
63
  end
62
64
  end
63
65
 
@@ -82,5 +84,4 @@ describe Praxis::RoutingConfig do
82
84
  end
83
85
  end
84
86
  end
85
-
86
87
  end
@@ -1,106 +1,109 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::Stage do
4
- subject(:stage) {Praxis::Stage.new("name","context")}
6
+ subject(:stage) { Praxis::Stage.new('name', 'context') }
5
7
 
6
- context "attributes" do
7
- its(:name) {should eq("name")}
8
- its(:context) {should eq("context")}
9
- its(:stages) {should eq([])}
10
- its(:before_callbacks) {should eq([])}
11
- its(:after_callbacks) {should eq([])}
8
+ context 'attributes' do
9
+ its(:name) { should eq('name') }
10
+ its(:context) { should eq('context') }
11
+ its(:stages) { should eq([]) }
12
+ its(:before_callbacks) { should eq([]) }
13
+ its(:after_callbacks) { should eq([]) }
12
14
  end
13
15
 
14
- context ".run" do
15
- it "sets up and execute callbacks" do
16
+ context '.run' do
17
+ it 'sets up and execute callbacks' do
16
18
  expect(stage).to receive('execute')
17
19
  expect(stage).to receive('execute_callbacks').twice
18
20
  stage.run
19
21
  end
20
22
  end
21
23
 
22
- context ".setup!" do
24
+ context '.setup!' do
23
25
  it 'should call setup_deferred_callbacks' do
24
26
  expect(stage).to receive('setup_deferred_callbacks!')
25
27
  stage.setup!
26
28
  end
27
29
  end
28
30
 
29
- context ".setup_deferred_callbacks!" do
30
- it "calls .before and .after for each stage name in @deferred_callbacks" do
31
+ context '.setup_deferred_callbacks!' do
32
+ it 'calls .before and .after for each stage name in @deferred_callbacks' do
31
33
  deferred_callbacks = {
32
- "stage" => {
33
- :before => [["before",nil]],
34
- :after => [["after",nil]]
35
- }}
36
- stage.instance_variable_set("@deferred_callbacks", deferred_callbacks)
37
- expect(stage).to receive("before")
38
- expect(stage).to receive("after")
34
+ 'stage' => {
35
+ before: [['before', nil]],
36
+ after: [['after', nil]]
37
+ }
38
+ }
39
+ stage.instance_variable_set('@deferred_callbacks', deferred_callbacks)
40
+ expect(stage).to receive('before')
41
+ expect(stage).to receive('after')
39
42
  stage.setup_deferred_callbacks!
40
43
  end
41
44
  end
42
45
 
43
- context ".execute" do
44
- it "runs all the stages" do
45
- double_stage = double("stage")
46
+ context '.execute' do
47
+ it 'runs all the stages' do
48
+ double_stage = double('stage')
46
49
  expect(double_stage).to receive('run')
47
- stage.instance_variable_set("@stages", [double_stage])
50
+ stage.instance_variable_set('@stages', [double_stage])
48
51
  stage.execute
49
52
  end
50
53
  end
51
54
 
52
- context ".execute_callbacks" do
53
- let(:callback) {double('callback')}
54
- it "executes every callback" do
55
- expect(callback).to receive("call")
55
+ context '.execute_callbacks' do
56
+ let(:callback) { double('callback') }
57
+ it 'executes every callback' do
58
+ expect(callback).to receive('call')
56
59
  stage.execute_callbacks([callback])
57
60
  end
58
61
  end
59
62
 
60
- context ".callback_args" do
61
- # TODO should this method return something else than nil?
62
- it "returns nil" do
63
+ context '.callback_args' do
64
+ # TODO: should this method return something else than nil?
65
+ it 'returns nil' do
63
66
  expect(stage.callback_args).to be(nil)
64
67
  end
65
68
  end
66
69
 
67
- context ".before" do
68
- it "adds block to @before_callbacks when stage_path is not provided" do
69
- stage.before {1}
70
+ context '.before' do
71
+ it 'adds block to @before_callbacks when stage_path is not provided' do
72
+ stage.before { 1 }
70
73
  expect(stage.before_callbacks.last.call).to be(1)
71
74
  end
72
75
 
73
- it "calls .before for the name matched stage" do
74
- double_stage = double("stage", name: "name")
76
+ it 'calls .before for the name matched stage' do
77
+ double_stage = double('stage', name: 'name')
75
78
  expect(double_stage).to receive('before')
76
- stage.instance_variable_set("@stages", [double_stage])
77
- stage.before("name")
79
+ stage.instance_variable_set('@stages', [double_stage])
80
+ stage.before('name')
78
81
  end
79
82
 
80
- it "adds to deferred_callbacks if no state name matched" do
81
- double_stage = double("stage", name: "name")
82
- stage.instance_variable_set("@stages", [double_stage])
83
- expect(stage.before("hello", "world")).to eq([["world",nil]])
83
+ it 'adds to deferred_callbacks if no state name matched' do
84
+ double_stage = double('stage', name: 'name')
85
+ stage.instance_variable_set('@stages', [double_stage])
86
+ expect(stage.before('hello', 'world')).to eq([['world', nil]])
84
87
  end
85
88
  end
86
89
 
87
- context ".after" do
88
- it "adds block to @after_callbacks when stage_path is not provided" do
89
- stage.after {1}
90
+ context '.after' do
91
+ it 'adds block to @after_callbacks when stage_path is not provided' do
92
+ stage.after { 1 }
90
93
  expect(stage.after_callbacks.last.call).to be(1)
91
94
  end
92
95
 
93
- it "calls .after for the name matched stage" do
94
- double_stage = double("stage", name: "name")
95
- expect(double_stage).to receive("after")
96
- stage.instance_variable_set("@stages", [double_stage])
97
- stage.after("name")
96
+ it 'calls .after for the name matched stage' do
97
+ double_stage = double('stage', name: 'name')
98
+ expect(double_stage).to receive('after')
99
+ stage.instance_variable_set('@stages', [double_stage])
100
+ stage.after('name')
98
101
  end
99
102
 
100
- it "adds to deferred_callbacks if no state name matched" do
101
- double_stage = double("stage", name: "name")
102
- stage.instance_variable_set("@stages", [double_stage])
103
- expect(stage.after("hello", "world")).to eq([["world",nil]])
103
+ it 'adds to deferred_callbacks if no state name matched' do
104
+ double_stage = double('stage', name: 'name')
105
+ stage.instance_variable_set('@stages', [double_stage])
106
+ expect(stage.after('hello', 'world')).to eq([['world', nil]])
104
107
  end
105
108
  end
106
109
  end