praxis 2.0.pre.17 → 2.0.pre.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -0
- data/.simplecov +3 -1
- data/.travis.yml +2 -1
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTING.md +2 -79
- data/Gemfile +5 -1
- data/Guardfile +6 -4
- data/LICENSE +0 -2
- data/MAINTAINERS.md +1 -0
- data/README.md +15 -22
- data/Rakefile +4 -2
- data/bin/praxis +55 -58
- data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -6
- data/lib/praxis/action_definition.rb +65 -95
- data/lib/praxis/api_definition.rb +21 -29
- data/lib/praxis/api_general_info.rb +55 -66
- data/lib/praxis/application.rb +15 -32
- data/lib/praxis/blueprint.rb +80 -73
- data/lib/praxis/bootloader.rb +24 -33
- data/lib/praxis/bootloader_stages/environment.rb +5 -10
- data/lib/praxis/bootloader_stages/file_loader.rb +3 -6
- data/lib/praxis/bootloader_stages/plugin_config_load.rb +4 -6
- data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +2 -2
- data/lib/praxis/bootloader_stages/plugin_loader.rb +3 -7
- data/lib/praxis/bootloader_stages/plugin_setup.rb +3 -3
- data/lib/praxis/bootloader_stages/routing.rb +5 -8
- data/lib/praxis/bootloader_stages/subgroup_loader.rb +2 -10
- data/lib/praxis/bootloader_stages/warn_unloaded_files.rb +15 -19
- data/lib/praxis/callbacks.rb +12 -11
- data/lib/praxis/collection.rb +11 -14
- data/lib/praxis/config.rb +17 -28
- data/lib/praxis/config_hash.rb +2 -1
- data/lib/praxis/controller.rb +7 -6
- data/lib/praxis/dispatcher.rb +34 -42
- data/lib/praxis/docs/open_api/info_object.rb +11 -8
- data/lib/praxis/docs/open_api/media_type_object.rb +18 -17
- data/lib/praxis/docs/open_api/operation_object.rb +7 -4
- data/lib/praxis/docs/open_api/parameter_object.rb +17 -14
- data/lib/praxis/docs/open_api/paths_object.rb +11 -9
- data/lib/praxis/docs/open_api/request_body_object.rb +14 -13
- data/lib/praxis/docs/open_api/response_object.rb +24 -18
- data/lib/praxis/docs/open_api/responses_object.rb +3 -1
- data/lib/praxis/docs/open_api/schema_object.rb +61 -29
- data/lib/praxis/docs/open_api/server_object.rb +5 -2
- data/lib/praxis/docs/open_api/tag_object.rb +9 -6
- data/lib/praxis/docs/open_api_generator.rb +114 -150
- data/lib/praxis/endpoint_definition.rb +60 -77
- data/lib/praxis/error_handler.rb +2 -2
- data/lib/praxis/exception.rb +2 -0
- data/lib/praxis/exceptions/config.rb +3 -1
- data/lib/praxis/exceptions/config_load.rb +2 -0
- data/lib/praxis/exceptions/config_validation.rb +3 -1
- data/lib/praxis/exceptions/invalid_configuration.rb +3 -1
- data/lib/praxis/exceptions/invalid_response.rb +3 -1
- data/lib/praxis/exceptions/invalid_trait.rb +3 -1
- data/lib/praxis/exceptions/stage_not_found.rb +3 -1
- data/lib/praxis/exceptions/validation.rb +4 -3
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +163 -149
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +18 -13
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +13 -9
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +14 -11
- data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +12 -9
- data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +8 -5
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +89 -65
- data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +68 -62
- data/lib/praxis/extensions/attribute_filtering.rb +3 -1
- data/lib/praxis/extensions/field_expansion.rb +6 -4
- data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +10 -8
- data/lib/praxis/extensions/field_selection/field_selector.rb +91 -92
- data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +12 -12
- data/lib/praxis/extensions/field_selection.rb +3 -1
- data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +6 -4
- data/lib/praxis/extensions/pagination/header_generator.rb +16 -11
- data/lib/praxis/extensions/pagination/ordering_params.rb +29 -28
- data/lib/praxis/extensions/pagination/pagination_handler.rb +44 -42
- data/lib/praxis/extensions/pagination/pagination_params.rb +29 -48
- data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +8 -7
- data/lib/praxis/extensions/pagination.rb +10 -15
- data/lib/praxis/extensions/rails_compat/request_methods.rb +3 -4
- data/lib/praxis/extensions/rails_compat.rb +2 -0
- data/lib/praxis/extensions/rendering.rb +12 -12
- data/lib/praxis/field_expander.rb +8 -9
- data/lib/praxis/file_group.rb +8 -12
- data/lib/praxis/finalizable.rb +1 -0
- data/lib/praxis/handlers/json.rb +5 -2
- data/lib/praxis/handlers/plain.rb +2 -1
- data/lib/praxis/handlers/www_form.rb +6 -3
- data/lib/praxis/handlers/{xml-sample.rb → xml_sample.rb} +26 -22
- data/lib/praxis/mapper/active_model_compat.rb +13 -10
- data/lib/praxis/mapper/resource.rb +196 -181
- data/lib/praxis/mapper/selector_generator.rb +106 -112
- data/lib/praxis/mapper/sequel_compat.rb +70 -67
- data/lib/praxis/media_type.rb +2 -2
- data/lib/praxis/media_type_identifier.rb +26 -22
- data/lib/praxis/middleware_app.rb +18 -15
- data/lib/praxis/multipart/parser.rb +46 -51
- data/lib/praxis/multipart/part.rb +78 -110
- data/lib/praxis/notifications.rb +2 -4
- data/lib/praxis/plugin.rb +11 -18
- data/lib/praxis/plugin_concern.rb +12 -15
- data/lib/praxis/plugins/mapper_plugin.rb +15 -13
- data/lib/praxis/plugins/pagination_plugin.rb +8 -6
- data/lib/praxis/plugins/rails_plugin.rb +33 -28
- data/lib/praxis/renderer.rb +11 -15
- data/lib/praxis/request.rb +48 -44
- data/lib/praxis/request_stages/action.rb +4 -6
- data/lib/praxis/request_stages/load_request.rb +2 -4
- data/lib/praxis/request_stages/request_stage.rb +19 -23
- data/lib/praxis/request_stages/response.rb +4 -6
- data/lib/praxis/request_stages/validate.rb +3 -5
- data/lib/praxis/request_stages/validate_params_and_headers.rb +15 -22
- data/lib/praxis/request_stages/validate_payload.rb +25 -28
- data/lib/praxis/request_superclassing.rb +3 -3
- data/lib/praxis/resource_definition.rb +1 -0
- data/lib/praxis/response.rb +24 -26
- data/lib/praxis/response_definition.rb +77 -122
- data/lib/praxis/response_template.rb +11 -15
- data/lib/praxis/responses/http.rb +23 -44
- data/lib/praxis/responses/internal_server_error.rb +18 -21
- data/lib/praxis/responses/multipart_ok.rb +4 -9
- data/lib/praxis/responses/validation_error.rb +8 -15
- data/lib/praxis/route.rb +8 -10
- data/lib/praxis/router/rack.rb +13 -7
- data/lib/praxis/router/simple.rb +10 -5
- data/lib/praxis/router.rb +27 -34
- data/lib/praxis/routing_config.rb +52 -29
- data/lib/praxis/simple_media_type.rb +5 -8
- data/lib/praxis/stage.rb +17 -25
- data/lib/praxis/tasks/api_docs.rb +17 -16
- data/lib/praxis/tasks/console.rb +3 -1
- data/lib/praxis/tasks/environment.rb +2 -0
- data/lib/praxis/tasks/routes.rb +26 -24
- data/lib/praxis/tasks.rb +3 -1
- data/lib/praxis/trait.rb +37 -46
- data/lib/praxis/types/fuzzy_hash.rb +13 -14
- data/lib/praxis/types/media_type_common.rb +11 -10
- data/lib/praxis/types/multipart_array/part_definition.rb +14 -17
- data/lib/praxis/types/multipart_array.rb +100 -115
- data/lib/praxis/validation_handler.rb +5 -3
- data/lib/praxis/version.rb +3 -1
- data/lib/praxis.rb +4 -5
- data/praxis.gemspec +22 -21
- data/spec/functional_spec.rb +44 -56
- data/spec/praxis/action_definition_spec.rb +39 -48
- data/spec/praxis/api_definition_spec.rb +45 -47
- data/spec/praxis/api_general_info_spec.rb +28 -29
- data/spec/praxis/application_spec.rb +18 -14
- data/spec/praxis/blueprint_spec.rb +33 -34
- data/spec/praxis/bootloader_spec.rb +32 -30
- data/spec/praxis/callbacks_spec.rb +37 -37
- data/spec/praxis/collection_spec.rb +18 -25
- data/spec/praxis/config_hash_spec.rb +5 -4
- data/spec/praxis/config_spec.rb +27 -26
- data/spec/praxis/controller_spec.rb +8 -9
- data/spec/praxis/endpoint_definition_spec.rb +25 -32
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +171 -114
- data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +22 -21
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +112 -60
- data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +37 -38
- data/spec/praxis/extensions/field_expansion_spec.rb +8 -10
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +14 -13
- data/spec/praxis/extensions/field_selection/field_selector_spec.rb +9 -16
- data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +50 -49
- data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +32 -31
- data/spec/praxis/extensions/rendering_spec.rb +9 -9
- data/spec/praxis/extensions/support/spec_resources_active_model.rb +32 -49
- data/spec/praxis/extensions/support/spec_resources_sequel.rb +48 -48
- data/spec/praxis/field_expander_spec.rb +6 -5
- data/spec/praxis/file_group_spec.rb +3 -1
- data/spec/praxis/handlers/json_spec.rb +6 -5
- data/spec/praxis/mapper/resource_spec.rb +39 -29
- data/spec/praxis/mapper/selector_generator_spec.rb +80 -46
- data/spec/praxis/media_type_identifier_spec.rb +13 -10
- data/spec/praxis/media_type_spec.rb +12 -12
- data/spec/praxis/middleware_app_spec.rb +23 -22
- data/spec/praxis/multipart/parser_spec.rb +7 -9
- data/spec/praxis/notifications_spec.rb +4 -4
- data/spec/praxis/plugin_concern_spec.rb +5 -6
- data/spec/praxis/renderer_spec.rb +10 -9
- data/spec/praxis/request_spec.rb +38 -41
- data/spec/praxis/request_stages/action_spec.rb +14 -15
- data/spec/praxis/request_stages/request_stage_spec.rb +30 -41
- data/spec/praxis/request_stages/validate_spec.rb +3 -1
- data/spec/praxis/response_definition_spec.rb +79 -92
- data/spec/praxis/response_spec.rb +35 -40
- data/spec/praxis/responses/internal_server_error_spec.rb +6 -9
- data/spec/praxis/responses/validation_error_spec.rb +17 -18
- data/spec/praxis/route_spec.rb +4 -7
- data/spec/praxis/router_spec.rb +69 -79
- data/spec/praxis/routing_config_spec.rb +15 -14
- data/spec/praxis/stage_spec.rb +56 -53
- data/spec/praxis/trait_spec.rb +17 -17
- data/spec/praxis/types/fuzzy_hash_spec.rb +11 -9
- data/spec/praxis/types/multipart_array/part_definition_spec.rb +3 -2
- data/spec/praxis/types/multipart_array_spec.rb +33 -48
- data/spec/spec_app/app/concerns/authenticated.rb +5 -5
- data/spec/spec_app/app/concerns/basic_api.rb +3 -1
- data/spec/spec_app/app/concerns/log_wrapper.rb +5 -3
- data/spec/spec_app/app/controllers/base_class.rb +6 -5
- data/spec/spec_app/app/controllers/instances.rb +31 -34
- data/spec/spec_app/app/controllers/volumes.rb +6 -6
- data/spec/spec_app/app/responses/multipart.rb +1 -2
- data/spec/spec_app/app/responses/other_response.rb +2 -2
- data/spec/spec_app/config/environment.rb +19 -6
- data/spec/spec_app/config.ru +4 -3
- data/spec/spec_app/design/api.rb +13 -15
- data/spec/spec_app/design/media_types/instance.rb +6 -6
- data/spec/spec_app/design/media_types/volume.rb +2 -1
- data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -1
- data/spec/spec_app/design/resources/instances.rb +11 -17
- data/spec/spec_app/design/resources/volume_snapshots.rb +4 -5
- data/spec/spec_app/design/resources/volumes.rb +4 -5
- data/spec/spec_helper.rb +11 -13
- data/spec/support/be_deep_equal_matcher.rb +5 -0
- data/spec/support/spec_authorization_plugin.rb +7 -12
- data/spec/support/spec_blueprints.rb +5 -4
- data/spec/support/spec_complex_authentication_plugin.rb +17 -34
- data/spec/support/spec_endpoint_definitions.rb +2 -3
- data/spec/support/spec_media_types.rb +28 -35
- data/spec/support/spec_resources.rb +22 -16
- data/spec/support/spec_simple_authentication_plugin.rb +5 -9
- data/tasks/loader.thor +4 -2
- data/tasks/thor/app.rb +7 -5
- data/tasks/thor/example.rb +23 -22
- data/tasks/thor/model.rb +7 -7
- data/tasks/thor/scaffold.rb +23 -23
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +0 -8
- data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +1 -2
- metadata +72 -84
- data/MAINTAINERS +0 -2
- data/TODO.md +0 -25
- data/spec/praxis/api_resource_spec.rb +0 -0
- data/spec/praxis/dispatcher_spec.rb +0 -0
- data/spec/spec_app/app/responses/bulk_response.rb +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative '../spec_helper'
|
3
4
|
|
4
5
|
describe Praxis::Renderer do
|
@@ -30,7 +31,7 @@ describe Praxis::Renderer do
|
|
30
31
|
address: {
|
31
32
|
state: true,
|
32
33
|
street: true,
|
33
|
-
resident:
|
34
|
+
resident: { name: true }
|
34
35
|
},
|
35
36
|
prior_addresses: { name: true },
|
36
37
|
work_address: true,
|
@@ -45,15 +46,15 @@ describe Praxis::Renderer do
|
|
45
46
|
subject(:output) { renderer.render(person, fields) }
|
46
47
|
|
47
48
|
it 'renders existing attributes' do
|
48
|
-
expect(output.keys).to match_array([
|
49
|
+
expect(output.keys).to match_array(%i[name full_name alive address prior_addresses metadata aliases])
|
49
50
|
|
50
51
|
expect(output[:name]).to eq person.name
|
51
52
|
expect(output[:full_name]).to eq(first: person.full_name.first, last: person.full_name.last)
|
52
53
|
expect(output[:alive]).to be false
|
53
54
|
|
54
55
|
expect(output[:address]).to eq(state: person.address.state,
|
55
|
-
|
56
|
-
|
56
|
+
street: person.address.street,
|
57
|
+
resident: { name: person.address.resident.name })
|
57
58
|
|
58
59
|
expected_prior_addresses = prior_addresses.collect { |addr| { name: addr.name } }
|
59
60
|
expect(output[:prior_addresses]).to match_array(expected_prior_addresses)
|
@@ -118,18 +119,18 @@ describe Praxis::Renderer do
|
|
118
119
|
|
119
120
|
context 'rendering stuff that breaks badly' do
|
120
121
|
it 'does not break badly' do
|
121
|
-
expect{renderer.render(person, {tags: true})}.to_not raise_error
|
122
|
+
expect { renderer.render(person, { tags: true }) }.to_not raise_error
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
125
126
|
context 'caching rendered objects' do
|
126
|
-
let(:fields) { {full_name: true} }
|
127
|
+
let(:fields) { { full_name: true } }
|
127
128
|
it 'caches and returns identical results for the same field objects' do
|
128
129
|
expect(person).to receive(:full_name).once.and_call_original
|
129
130
|
|
130
|
-
|
131
|
-
|
132
|
-
expect(
|
131
|
+
render1 = renderer.render(person, fields)
|
132
|
+
render2 = renderer.render(person, fields)
|
133
|
+
expect(render1).to be(render2)
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
data/spec/praxis/request_spec.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Praxis::Request do
|
4
|
-
let(:path) { '/instances/1?junk=foo&api_version=1.0' }
|
6
|
+
let(:path) { '/instances/1?junk=foo&api_version=1.0' }
|
5
7
|
let(:rack_input) { StringIO.new('{"something": "given"}') }
|
6
|
-
let(:env_content_type){ 'application/json' }
|
8
|
+
let(:env_content_type) { 'application/json' }
|
7
9
|
let(:env) do
|
8
10
|
env = Rack::MockRequest.env_for(path)
|
9
11
|
env['rack.input'] = rack_input
|
@@ -17,9 +19,9 @@ describe Praxis::Request do
|
|
17
19
|
|
18
20
|
let(:context) do
|
19
21
|
{
|
20
|
-
params: [Attributor::
|
21
|
-
headers: [Attributor::
|
22
|
-
payload: [Attributor::
|
22
|
+
params: [Attributor::ROOT_PREFIX, 'params'],
|
23
|
+
headers: [Attributor::ROOT_PREFIX, 'headers'],
|
24
|
+
payload: [Attributor::ROOT_PREFIX, 'payload']
|
23
25
|
}.freeze
|
24
26
|
end
|
25
27
|
|
@@ -29,9 +31,9 @@ describe Praxis::Request do
|
|
29
31
|
request
|
30
32
|
end
|
31
33
|
|
32
|
-
its(:verb) { should eq(
|
34
|
+
its(:verb) { should eq('GET') }
|
33
35
|
its(:path) { should eq('/instances/1') }
|
34
|
-
its(:raw_params) { should eq({'junk' => 'foo'}) }
|
36
|
+
its(:raw_params) { should eq({ 'junk' => 'foo' }) }
|
35
37
|
its(:version) { should eq('1.0') }
|
36
38
|
|
37
39
|
context 'path versioning' do
|
@@ -42,26 +44,24 @@ describe Praxis::Request do
|
|
42
44
|
allow(
|
43
45
|
Praxis::ApiDefinition.instance.info
|
44
46
|
).to receive(:base_path).and_return('/api/v:api_version')
|
45
|
-
|
46
47
|
end
|
47
48
|
|
48
49
|
let(:path) { '/api/v2.0/instances/1' }
|
49
50
|
|
50
|
-
|
51
51
|
its(:version) { should eq '2.0' }
|
52
|
-
#its('class.path_version_prefix'){ should eq("/v") }
|
53
|
-
#its(:path_version_matcher){ should be_kind_of(Regexp) }
|
54
|
-
#it 'uses a "/v*" default matcher with a "version" named capture' do
|
52
|
+
# its('class.path_version_prefix'){ should eq("/v") }
|
53
|
+
# its(:path_version_matcher){ should be_kind_of(Regexp) }
|
54
|
+
# it 'uses a "/v*" default matcher with a "version" named capture' do
|
55
55
|
# match = subject.path_version_matcher.match("/v5.5/something")
|
56
56
|
# expect(match).to_not be(nil)
|
57
57
|
# expect(match['version']).to eq("5.5")
|
58
|
-
#end
|
58
|
+
# end
|
59
59
|
end
|
60
60
|
|
61
61
|
context 'loading api version' do
|
62
|
-
#let(:request) { Praxis::Request.new(env) }
|
63
|
-
subject(:version){ request.version }
|
64
|
-
let(:versioning_scheme){ Praxis::Request::VERSION_USING_DEFAULTS }
|
62
|
+
# let(:request) { Praxis::Request.new(env) }
|
63
|
+
subject(:version) { request.version }
|
64
|
+
let(:versioning_scheme) { Praxis::Request::VERSION_USING_DEFAULTS }
|
65
65
|
before do
|
66
66
|
allow(
|
67
67
|
Praxis::Application.instance
|
@@ -69,18 +69,18 @@ describe Praxis::Request do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
context 'using X-Api-Header' do
|
72
|
-
let(:env){ {'HTTP_X_API_VERSION' =>
|
73
|
-
let(:versioning_scheme){ :header }
|
72
|
+
let(:env) { { 'HTTP_X_API_VERSION' => '5.0', 'PATH_INFO' => '/something' } }
|
73
|
+
let(:versioning_scheme) { :header }
|
74
74
|
it { should eq('5.0') }
|
75
75
|
end
|
76
76
|
context 'using query param' do
|
77
77
|
let(:env) { Rack::MockRequest.env_for('/instances/1?junk=foo&api_version=5.0') }
|
78
|
-
let(:versioning_scheme){ :params }
|
78
|
+
let(:versioning_scheme) { :params }
|
79
79
|
it { should eq('5.0') }
|
80
80
|
end
|
81
81
|
context 'using path (with the default pattern matcher)' do
|
82
|
-
let(:env){ Rack::MockRequest.env_for('/v5.0/instances/1?junk=foo') }
|
83
|
-
let(:versioning_scheme){ :path }
|
82
|
+
let(:env) { Rack::MockRequest.env_for('/v5.0/instances/1?junk=foo') }
|
83
|
+
let(:versioning_scheme) { :path }
|
84
84
|
|
85
85
|
before do
|
86
86
|
allow(
|
@@ -92,21 +92,21 @@ describe Praxis::Request do
|
|
92
92
|
|
93
93
|
context 'using a method that it is not allowed in the definition' do
|
94
94
|
context 'allowing query param but passing it through a header' do
|
95
|
-
let(:env){ {'HTTP_X_API_VERSION' =>
|
96
|
-
let(:versioning_scheme){ :params }
|
95
|
+
let(:env) { { 'HTTP_X_API_VERSION' => '5.0', 'PATH_INFO' => '/something' } }
|
96
|
+
let(:versioning_scheme) { :params }
|
97
97
|
it { should eq('n/a') }
|
98
98
|
end
|
99
99
|
context 'allowing header but passing it through param' do
|
100
100
|
let(:env) { Rack::MockRequest.env_for('/instances/1?junk=foo&api_version=5.0') }
|
101
|
-
let(:versioning_scheme){ :header }
|
101
|
+
let(:versioning_scheme) { :header }
|
102
102
|
it { should eq('n/a') }
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
106
|
context 'using defaults' do
|
107
|
-
subject(:version){ request.version }
|
107
|
+
subject(:version) { request.version }
|
108
108
|
context 'would succeed if passed through the header' do
|
109
|
-
let(:env){ {'HTTP_X_API_VERSION' =>
|
109
|
+
let(:env) { { 'HTTP_X_API_VERSION' => '5.0', 'PATH_INFO' => '/something' } }
|
110
110
|
it { should eq('5.0') }
|
111
111
|
end
|
112
112
|
context 'would succeed if passed through params' do
|
@@ -126,9 +126,9 @@ describe Praxis::Request do
|
|
126
126
|
form_data
|
127
127
|
end
|
128
128
|
|
129
|
-
let(:rack_input)
|
129
|
+
let(:rack_input) do
|
130
130
|
StringIO.new(form.body.to_s)
|
131
|
-
|
131
|
+
end
|
132
132
|
|
133
133
|
let(:env) do
|
134
134
|
env = Rack::MockRequest.env_for('/instances/1?junk=foo&api_version=1.0')
|
@@ -138,21 +138,18 @@ describe Praxis::Request do
|
|
138
138
|
env
|
139
139
|
end
|
140
140
|
|
141
|
-
#its(:multipart?) { should be(true) }
|
141
|
+
# its(:multipart?) { should be(true) }
|
142
142
|
|
143
143
|
it 'works' do
|
144
|
-
#p request #.body
|
145
|
-
#p request #.parts
|
144
|
+
# p request #.body
|
145
|
+
# p request #.parts
|
146
146
|
end
|
147
|
-
|
148
|
-
|
149
147
|
end
|
150
148
|
|
151
149
|
context '#load_headers' do
|
152
|
-
|
153
150
|
it 'is done preserving the original case' do
|
154
151
|
request.load_headers(context[:headers])
|
155
|
-
expect(request.headers).to eq({
|
152
|
+
expect(request.headers).to eq({ 'Authorization' => 'Secret' })
|
156
153
|
end
|
157
154
|
|
158
155
|
it 'performs it using the memoized rack keys from the action (Hacky but...performance is important)' do
|
@@ -161,7 +158,7 @@ describe Praxis::Request do
|
|
161
158
|
end
|
162
159
|
end
|
163
160
|
|
164
|
-
context
|
161
|
+
context 'performs request validation' do
|
165
162
|
before(:each) do
|
166
163
|
request.load_headers(context[:headers])
|
167
164
|
request.load_params(context[:params])
|
@@ -205,17 +202,17 @@ describe Praxis::Request do
|
|
205
202
|
end
|
206
203
|
|
207
204
|
context '#load_payload' do
|
208
|
-
let(:load_context){ context[:payload] }
|
209
|
-
let(:parsed_result){ double(
|
205
|
+
let(:load_context) { context[:payload] }
|
206
|
+
let(:parsed_result) { double('parsed') }
|
210
207
|
|
211
208
|
after do
|
212
|
-
expect(request.action.payload).to receive(:load).with(parsed_result, load_context, content_type: request.content_type.to_s
|
213
|
-
request.load_payload(
|
209
|
+
expect(request.action.payload).to receive(:load).with(parsed_result, load_context, content_type: request.content_type.to_s)
|
210
|
+
request.load_payload(load_context)
|
214
211
|
end
|
215
212
|
|
216
213
|
context 'that is json encoded' do
|
217
214
|
let(:rack_input) { StringIO.new('{"one":1,"sub_hash":{"first":"hello"}}') }
|
218
|
-
let(:env_content_type){ 'application/json' }
|
215
|
+
let(:env_content_type) { 'application/json' }
|
219
216
|
let(:parsed_result) { Praxis::Handlers::JSON.new.parse(request.raw_payload) }
|
220
217
|
|
221
218
|
it 'decodes using the JSON handler' do end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Praxis::RequestStages::Action do
|
4
|
-
|
5
6
|
let(:controller) do
|
6
7
|
Class.new do
|
7
8
|
include Praxis::Controller
|
8
9
|
end.new(request)
|
9
10
|
end
|
10
11
|
|
11
|
-
let(:action) { double(
|
12
|
-
let(:response){ Praxis::Responses::Ok.new }
|
13
|
-
let(:app){ double(
|
14
|
-
let(:action_stage){ Praxis::RequestStages::Action.new(action.name,app) }
|
12
|
+
let(:action) { double('action', name: 'foo') }
|
13
|
+
let(:response) { Praxis::Responses::Ok.new }
|
14
|
+
let(:app) { double('App', controller: controller, action: action, request: request) }
|
15
|
+
let(:action_stage) { Praxis::RequestStages::Action.new(action.name, app) }
|
15
16
|
|
16
17
|
let(:request) do
|
17
18
|
env = Rack::MockRequest.env_for('/instances/1?cloud_id=1&api_version=1.0')
|
@@ -23,19 +24,17 @@ describe Praxis::RequestStages::Action do
|
|
23
24
|
request
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
27
|
context '.execute' do
|
28
28
|
before do
|
29
29
|
expect(controller).to receive(action_stage.name) do |args|
|
30
30
|
if args
|
31
31
|
expect(args).to eq({})
|
32
32
|
else
|
33
|
-
|
33
|
+
expect(args).to eq(nil)
|
34
34
|
end
|
35
35
|
end.and_return(controller_response)
|
36
|
-
|
37
36
|
end
|
38
|
-
let(:controller_response){ controller.response }
|
37
|
+
let(:controller_response) { controller.response }
|
39
38
|
|
40
39
|
it 'always call the right controller method' do
|
41
40
|
action_stage.execute
|
@@ -47,28 +46,28 @@ describe Praxis::RequestStages::Action do
|
|
47
46
|
end
|
48
47
|
|
49
48
|
it 'sends the right ActiveSupport::Notification' do
|
50
|
-
expect(ActiveSupport::Notifications).to receive(:instrument).with('praxis.request_stage.execute', {controller: an_instance_of(controller.class)}).and_call_original
|
49
|
+
expect(ActiveSupport::Notifications).to receive(:instrument).with('praxis.request_stage.execute', { controller: an_instance_of(controller.class) }).and_call_original
|
51
50
|
action_stage.execute
|
52
51
|
end
|
53
52
|
|
54
53
|
context 'if the controller method returns a string' do
|
55
|
-
let(:controller_response){
|
54
|
+
let(:controller_response) { 'this is the body' }
|
56
55
|
it 'sets the response body with it (and save the request too)' do
|
57
56
|
action_stage.execute
|
58
|
-
expect(controller.response.body).to eq(
|
57
|
+
expect(controller.response.body).to eq('this is the body')
|
59
58
|
end
|
60
59
|
end
|
61
60
|
context 'if the controller method returns a response object' do
|
62
|
-
let(:controller_response){ Praxis::Responses::Created.new }
|
61
|
+
let(:controller_response) { Praxis::Responses::Created.new }
|
63
62
|
it 'set that response in the controller' do
|
64
63
|
action_stage.execute
|
65
64
|
expect(controller.response).to eq(controller_response)
|
66
65
|
end
|
67
66
|
end
|
68
67
|
context 'if the controller method returns neither a string or a response' do
|
69
|
-
let(:controller_response){ nil }
|
68
|
+
let(:controller_response) { nil }
|
70
69
|
it 'an error is raised ' do
|
71
|
-
expect{ action_stage.execute }.to raise_error(/Only Response objects or Strings allowed/)
|
70
|
+
expect { action_stage.execute }.to raise_error(/Only Response objects or Strings allowed/)
|
72
71
|
end
|
73
72
|
end
|
74
73
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Praxis::RequestStages::RequestStage do
|
4
|
-
|
5
6
|
let(:controller_class) do
|
6
7
|
Class.new do
|
7
8
|
include Praxis::Controller
|
@@ -11,15 +12,14 @@ describe Praxis::RequestStages::RequestStage do
|
|
11
12
|
let(:stage_class) { Class.new(Praxis::RequestStages::RequestStage) }
|
12
13
|
|
13
14
|
let(:request) { Praxis::Request.new({}) }
|
14
|
-
let(:controller){ controller_class.new(request) }
|
15
|
+
let(:controller) { controller_class.new(request) }
|
15
16
|
|
17
|
+
let(:action) { instance_double('Praxis::ActionDefinition') }
|
18
|
+
let(:context) { double('context', controller: controller, action: action) }
|
16
19
|
|
17
|
-
let(:
|
18
|
-
let(:
|
19
|
-
|
20
|
-
let(:substage_1) { instance_double('Praxis::RequestStage') }
|
21
|
-
let(:substage_2) { instance_double('Praxis::RequestStage') }
|
22
|
-
let(:substage_3) { instance_double('Praxis::RequestStage') }
|
20
|
+
let(:substage1) { instance_double('Praxis::RequestStage') }
|
21
|
+
let(:substage2) { instance_double('Praxis::RequestStage') }
|
22
|
+
let(:substage3) { instance_double('Praxis::RequestStage') }
|
23
23
|
|
24
24
|
let(:before_callbacks) { double('before_callbacks') }
|
25
25
|
let(:after_callbacks) { double('after_callbacks') }
|
@@ -28,19 +28,18 @@ describe Praxis::RequestStages::RequestStage do
|
|
28
28
|
|
29
29
|
subject(:stage) { stage_class.new(:action, context) }
|
30
30
|
|
31
|
-
|
32
31
|
before do
|
33
32
|
# clear any pre-existing callbacks that may have been added by plugins
|
34
|
-
controller_class.before_callbacks =
|
35
|
-
controller_class.after_callbacks =
|
33
|
+
controller_class.before_callbacks = ({})
|
34
|
+
controller_class.after_callbacks = ({})
|
36
35
|
end
|
37
36
|
|
38
37
|
context 'for an abstract stage' do
|
39
38
|
subject(:stage) { Praxis::RequestStages::RequestStage.new(:action, context) }
|
40
39
|
it 'raises NotImplementedError for undefined #execute' do
|
41
|
-
expect
|
40
|
+
expect do
|
42
41
|
stage.execute
|
43
|
-
|
42
|
+
end.to raise_error(NotImplementedError, /Subclass must implement Stage#execute/)
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
@@ -57,16 +56,16 @@ describe Praxis::RequestStages::RequestStage do
|
|
57
56
|
end
|
58
57
|
end
|
59
58
|
|
60
|
-
context
|
59
|
+
context '#execute' do
|
61
60
|
before do
|
62
|
-
stage.stages.push(
|
61
|
+
stage.stages.push(substage1, substage2, substage3)
|
63
62
|
end
|
64
63
|
|
65
64
|
context 'when all stages succeed' do
|
66
|
-
it
|
67
|
-
expect(
|
68
|
-
expect(
|
69
|
-
expect(
|
65
|
+
it 'runs them all and returns nil' do
|
66
|
+
expect(substage1).to receive(:run).once
|
67
|
+
expect(substage2).to receive(:run).once
|
68
|
+
expect(substage3).to receive(:run).once
|
70
69
|
expect(stage.execute).to be(nil)
|
71
70
|
end
|
72
71
|
end
|
@@ -74,12 +73,12 @@ describe Praxis::RequestStages::RequestStage do
|
|
74
73
|
context 'when one stage returns a Response' do
|
75
74
|
let(:response) { Praxis::Responses::Ok.new }
|
76
75
|
before do
|
77
|
-
expect(
|
78
|
-
expect(
|
76
|
+
expect(substage1).to receive(:run).once
|
77
|
+
expect(substage2).to receive(:run).once.and_return(response)
|
79
78
|
end
|
80
79
|
|
81
|
-
it
|
82
|
-
expect(
|
80
|
+
it 'runs no further stages after that' do
|
81
|
+
expect(substage3).to_not receive(:run)
|
83
82
|
stage.execute
|
84
83
|
end
|
85
84
|
|
@@ -88,12 +87,10 @@ describe Praxis::RequestStages::RequestStage do
|
|
88
87
|
|
89
88
|
expect(controller.response).to be(response)
|
90
89
|
end
|
91
|
-
|
92
90
|
end
|
93
91
|
end
|
94
92
|
|
95
|
-
context
|
96
|
-
|
93
|
+
context '#run' do
|
97
94
|
let(:before_callbacks) { double('before_callbacks') }
|
98
95
|
let(:after_callbacks) { double('after_callbacks') }
|
99
96
|
|
@@ -113,14 +110,13 @@ describe Praxis::RequestStages::RequestStage do
|
|
113
110
|
allow(controller_class).to receive(:after_callbacks).once.and_return(controller_after_callbacks)
|
114
111
|
end
|
115
112
|
|
116
|
-
it
|
113
|
+
it 'sets up and executes callbacks' do
|
117
114
|
expect(stage).to receive(:execute)
|
118
115
|
expect(stage).to receive(:execute_callbacks).once.with(before_callbacks)
|
119
116
|
expect(stage).to receive(:execute_callbacks).once.with(after_callbacks)
|
120
117
|
expect(stage).to receive(:execute_controller_callbacks).once.with(controller_before_callbacks)
|
121
118
|
expect(stage).to receive(:execute_controller_callbacks).once.with(controller_after_callbacks)
|
122
119
|
end
|
123
|
-
|
124
120
|
end
|
125
121
|
|
126
122
|
context 'when the before execute_controller_callbacks return a Response' do
|
@@ -131,7 +127,6 @@ describe Praxis::RequestStages::RequestStage do
|
|
131
127
|
expect(stage).to receive(:execute_controller_callbacks).once.and_return(response)
|
132
128
|
end
|
133
129
|
|
134
|
-
|
135
130
|
it 'does not call "execute"' do
|
136
131
|
expect(stage).to_not receive(:execute)
|
137
132
|
end
|
@@ -140,22 +135,20 @@ describe Praxis::RequestStages::RequestStage do
|
|
140
135
|
expect(stage).to_not receive(:after_callbacks)
|
141
136
|
expect(controller_class).to_not receive(:after_callbacks)
|
142
137
|
end
|
143
|
-
|
144
138
|
end
|
145
139
|
|
146
140
|
context 'with substages' do
|
147
141
|
before do
|
148
|
-
stage.stages.push(
|
142
|
+
stage.stages.push(substage1, substage2, substage3)
|
149
143
|
end
|
150
144
|
|
151
|
-
|
152
145
|
context 'when one returns a Response' do
|
153
146
|
let(:response) { Praxis::Responses::Unauthorized.new }
|
154
147
|
|
155
148
|
before do
|
156
|
-
expect(
|
157
|
-
expect(
|
158
|
-
expect(
|
149
|
+
expect(substage1).to receive(:run).once
|
150
|
+
expect(substage2).to receive(:run).once.and_return(response)
|
151
|
+
expect(substage3).to_not receive(:run)
|
159
152
|
end
|
160
153
|
|
161
154
|
it 'runs no after callbacks (including from the controller) ' do
|
@@ -165,14 +158,10 @@ describe Praxis::RequestStages::RequestStage do
|
|
165
158
|
|
166
159
|
it 'assigns controller.response' do
|
167
160
|
# twice, because we do it once in #execute, and again in #run...
|
168
|
-
expect(controller).to receive(:response=)
|
169
|
-
with(response).twice.and_call_original
|
161
|
+
expect(controller).to receive(:response=)
|
162
|
+
.with(response).twice.and_call_original
|
170
163
|
end
|
171
|
-
|
172
164
|
end
|
173
165
|
end
|
174
166
|
end
|
175
|
-
|
176
|
-
|
177
|
-
|
178
167
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe Praxis::RequestStages::Validate do
|
@@ -19,7 +21,7 @@ describe Praxis::RequestStages::Validate do
|
|
19
21
|
|
20
22
|
let(:request) do
|
21
23
|
r = Praxis::Request.new(env)
|
22
|
-
r.route_params = {id: 1}
|
24
|
+
r.route_params = { id: 1 }
|
23
25
|
r.action = action
|
24
26
|
r
|
25
27
|
end
|