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.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -0
- data/.simplecov +3 -1
- data/.travis.yml +2 -1
- data/CHANGELOG.md +6 -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 +64 -94
- 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 +64 -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 +10 -13
- 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 +6 -3
- 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 +16 -16
- data/lib/praxis/docs/open_api/server_object.rb +5 -2
- data/lib/praxis/docs/open_api/tag_object.rb +6 -3
- data/lib/praxis/docs/open_api_generator.rb +92 -95
- 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 +171 -180
- 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 +46 -47
- 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 -16
- data/lib/praxis/request_stages/validate_payload.rb +25 -27
- data/lib/praxis/request_superclassing.rb +3 -3
- data/lib/praxis/resource_definition.rb +1 -0
- data/lib/praxis/response.rb +13 -25
- 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 +15 -15
- 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 +88 -112
- 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 +40 -52
- data/spec/praxis/action_definition_spec.rb +36 -46
- 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 +27 -30
- data/spec/praxis/mapper/selector_generator_spec.rb +50 -50
- 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 +28 -39
- 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 -18
- 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 +5 -5
- 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 +9 -15
- 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 +2 -1
- 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 +20 -18
- 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,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
|
9
|
+
def self.name
|
10
|
+
'MyResource'
|
11
|
+
end
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
12
|
-
let(:routing_block) {
|
13
|
-
let(:base_path){ '' }
|
14
|
-
let(:default_route_prefix) { "
|
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
|
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(
|
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
|
data/spec/praxis/stage_spec.rb
CHANGED
@@ -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(
|
6
|
+
subject(:stage) { Praxis::Stage.new('name', 'context') }
|
5
7
|
|
6
|
-
context
|
7
|
-
its(:name) {should eq(
|
8
|
-
its(:context) {should eq(
|
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
|
15
|
-
it
|
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
|
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
|
30
|
-
it
|
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
|
-
|
33
|
-
:
|
34
|
-
:
|
35
|
-
}
|
36
|
-
|
37
|
-
|
38
|
-
expect(stage).to receive(
|
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
|
44
|
-
it
|
45
|
-
double_stage = double(
|
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(
|
50
|
+
stage.instance_variable_set('@stages', [double_stage])
|
48
51
|
stage.execute
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
52
|
-
context
|
53
|
-
let(:callback) {double('callback')}
|
54
|
-
it
|
55
|
-
expect(callback).to receive(
|
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
|
61
|
-
# TODO should this method return something else than nil?
|
62
|
-
it
|
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
|
68
|
-
it
|
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
|
74
|
-
double_stage = double(
|
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(
|
77
|
-
stage.before(
|
79
|
+
stage.instance_variable_set('@stages', [double_stage])
|
80
|
+
stage.before('name')
|
78
81
|
end
|
79
82
|
|
80
|
-
it
|
81
|
-
double_stage = double(
|
82
|
-
stage.instance_variable_set(
|
83
|
-
expect(stage.before(
|
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
|
88
|
-
it
|
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
|
94
|
-
double_stage = double(
|
95
|
-
expect(double_stage).to receive(
|
96
|
-
stage.instance_variable_set(
|
97
|
-
stage.after(
|
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
|
101
|
-
double_stage = double(
|
102
|
-
stage.instance_variable_set(
|
103
|
-
expect(stage.after(
|
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
|
data/spec/praxis/trait_spec.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
4
4
|
|
5
|
+
describe Praxis::Trait do
|
5
6
|
subject(:trait) do
|
6
7
|
Praxis::Trait.new do
|
7
8
|
description 'my awesome trait'
|
@@ -19,14 +20,13 @@ describe Praxis::Trait do
|
|
19
20
|
end
|
20
21
|
params do
|
21
22
|
attribute :order, String,
|
22
|
-
|
23
|
+
description: 'Field to sort by.'
|
23
24
|
end
|
24
25
|
|
25
26
|
headers do
|
26
|
-
header
|
27
|
-
key
|
27
|
+
header 'Authorization'
|
28
|
+
key 'Header2', String, required: true, null: false
|
28
29
|
end
|
29
|
-
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -35,25 +35,24 @@ describe Praxis::Trait do
|
|
35
35
|
|
36
36
|
its([:description]) { should eq('my awesome trait') }
|
37
37
|
|
38
|
-
its([
|
39
|
-
its([
|
38
|
+
its(%i[responses something]) { should eq({}) }
|
39
|
+
its(%i[responses nothing]) { should eq({}) }
|
40
40
|
|
41
|
-
its([
|
42
|
-
its([
|
43
|
-
its([
|
41
|
+
its(%i[params app_name type name]) { should eq 'String' }
|
42
|
+
its(%i[params order type name]) { should eq 'String' }
|
43
|
+
its(%i[routing prefix]) { should eq '/:app_name' }
|
44
44
|
|
45
|
-
its([:headers,
|
45
|
+
its([:headers, 'Header2']) { should include({ required: true, null: false }) }
|
46
46
|
context 'using the special DSL syntax for headers' do
|
47
|
-
subject(:dsl_header) { describe[:headers][
|
48
|
-
its([:required]){ should be(true) }
|
49
|
-
its([:null]){ should be_nil }
|
50
|
-
its([:type]){ should eq(
|
47
|
+
subject(:dsl_header) { describe[:headers]['Authorization'] }
|
48
|
+
its([:required]) { should be(true) }
|
49
|
+
its([:null]) { should be_nil }
|
50
|
+
its([:type]) { should eq({ id: 'Attributor-String', name: 'String', family: 'string' }) }
|
51
51
|
end
|
52
|
-
|
53
52
|
end
|
54
53
|
|
55
54
|
context 'apply!' do
|
56
|
-
let(:target) { double(
|
55
|
+
let(:target) { double('Target') }
|
57
56
|
it 'does' do
|
58
57
|
expect(target).to receive(:routing).once
|
59
58
|
expect(target).to receive(:response).twice
|
@@ -1,20 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
describe Praxis::Types::FuzzyHash do
|
6
|
+
let(:initial_value) do
|
7
|
+
{
|
8
|
+
'key' => 'value',
|
9
|
+
/bob/ => 'rob',
|
10
|
+
/\d+/ => 'one'
|
11
|
+
}
|
12
|
+
end
|
10
13
|
|
11
14
|
subject(:hash) { Praxis::Types::FuzzyHash.new(initial_value) }
|
12
15
|
|
13
16
|
its(['key']) { should eq 'value' }
|
14
17
|
its([/bob/]) { should eq 'rob' }
|
15
18
|
its(['bobby']) { should eq 'rob' }
|
16
|
-
|
19
|
+
|
17
20
|
its([1]) { should eq 'one' }
|
18
21
|
its(['1']) { should eq 'one' }
|
19
22
|
end
|
20
|
-
|
@@ -1,15 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
+
describe Praxis::Types::MultipartArray do
|
5
6
|
let(:type) do
|
6
7
|
Class.new(Praxis::Types::MultipartArray) do
|
7
|
-
|
8
|
+
options[:case_insensitive_load] = true
|
8
9
|
|
9
10
|
part 'title', String, required: true
|
10
11
|
part(/nam/, String, regexp: /Bob/i)
|
11
12
|
|
12
|
-
part
|
13
|
+
part(/stuff/) do
|
13
14
|
payload Hash
|
14
15
|
end
|
15
16
|
|
@@ -22,33 +23,31 @@ describe Praxis::Types::MultipartArray do
|
|
22
23
|
file 'thumbnail', Attributor::Tempfile
|
23
24
|
|
24
25
|
part 'image', Attributor::Tempfile, filename: true
|
25
|
-
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
29
|
let(:form) do
|
31
30
|
form_data = MIME::Multipart::FormData.new
|
32
31
|
entity = MIME::Text.new('Bob')
|
33
|
-
form_data.add entity,'name'
|
32
|
+
form_data.add entity, 'name'
|
34
33
|
|
35
34
|
entity = MIME::Text.new('Captain')
|
36
|
-
form_data.add entity,'title'
|
35
|
+
form_data.add entity, 'title'
|
37
36
|
|
38
37
|
entity = MIME::Application.new('file1')
|
39
|
-
form_data.add entity,'files', 'file1'
|
38
|
+
form_data.add entity, 'files', 'file1'
|
40
39
|
|
41
40
|
entity = MIME::Application.new('file2')
|
42
|
-
form_data.add entity,'files', 'file2'
|
41
|
+
form_data.add entity, 'files', 'file2'
|
43
42
|
|
44
43
|
entity = MIME::Application.new('{"first_name": "Frank"}', 'json')
|
45
|
-
form_data.add entity,'stuff2'
|
44
|
+
form_data.add entity, 'stuff2'
|
46
45
|
|
47
46
|
entity = MIME::Application.new('SOMEBINARYDATA', 'jpg')
|
48
|
-
form_data.add entity,'thumbnail', 'thumb.jpg'
|
47
|
+
form_data.add entity, 'thumbnail', 'thumb.jpg'
|
49
48
|
|
50
49
|
entity = MIME::Application.new('', 'jpg')
|
51
|
-
form_data.add entity,'image', 'image.jpg'
|
50
|
+
form_data.add entity, 'image', 'image.jpg'
|
52
51
|
|
53
52
|
form_data
|
54
53
|
end
|
@@ -59,7 +58,6 @@ describe Praxis::Types::MultipartArray do
|
|
59
58
|
subject(:payload) { type.load(body, content_type: content_type) }
|
60
59
|
|
61
60
|
it 'validates' do
|
62
|
-
part = payload.part('files').first
|
63
61
|
expect(payload.validate).to be_empty
|
64
62
|
end
|
65
63
|
|
@@ -94,9 +92,9 @@ describe Praxis::Types::MultipartArray do
|
|
94
92
|
end
|
95
93
|
end
|
96
94
|
|
97
|
-
let(:json_payload) { {sub_hash: {key:'value'}}.to_json }
|
95
|
+
let(:json_payload) { { sub_hash: { key: 'value' } }.to_json }
|
98
96
|
let(:body) { StringIO.new("--boundary\r\nContent-Disposition: form-data; name=blah\r\n\r\n#{json_payload}\r\n--boundary--") }
|
99
|
-
let(:content_type) {
|
97
|
+
let(:content_type) { 'multipart/form-data; boundary=boundary' }
|
100
98
|
|
101
99
|
it do
|
102
100
|
expect(payload.part('blah').payload['sub_hash']).to eq('key' => 'value')
|
@@ -117,9 +115,9 @@ describe Praxis::Types::MultipartArray do
|
|
117
115
|
end
|
118
116
|
end
|
119
117
|
|
120
|
-
let(:json_payload) { {attr: 'value'}.to_json }
|
118
|
+
let(:json_payload) { { attr: 'value' }.to_json }
|
121
119
|
let(:body) { StringIO.new("--boundary\r\nContent-Disposition: form-data; name=blah\r\n\r\n#{json_payload}\r\n--boundary--") }
|
122
|
-
let(:content_type) {
|
120
|
+
let(:content_type) { 'multipart/form-data; boundary=boundary' }
|
123
121
|
|
124
122
|
it do
|
125
123
|
expect(payload.part('blah').payload.class.ancestors).to include(Attributor::Struct)
|
@@ -142,7 +140,7 @@ describe Praxis::Types::MultipartArray do
|
|
142
140
|
|
143
141
|
context 'attributes' do
|
144
142
|
subject(:attributes) { description[:attributes] }
|
145
|
-
its(:keys) { should match_array [
|
143
|
+
its(:keys) { should match_array %w[title files thumbnail image] }
|
146
144
|
|
147
145
|
context 'the "title" part' do
|
148
146
|
subject(:title_description) { attributes['title'] }
|
@@ -172,14 +170,12 @@ describe Praxis::Types::MultipartArray do
|
|
172
170
|
expect(filename[:options]).to eq(regexp: /file/)
|
173
171
|
expect(filename[:type]).to eq Attributor::String.describe
|
174
172
|
end
|
175
|
-
|
176
173
|
end
|
177
|
-
|
178
174
|
end
|
179
175
|
|
180
176
|
context 'pattern attributes' do
|
181
177
|
subject(:pattern_attributes) { description[:pattern_attributes] }
|
182
|
-
its(:keys) { should match_array [
|
178
|
+
its(:keys) { should match_array %w[nam stuff] }
|
183
179
|
end
|
184
180
|
|
185
181
|
context 'with no parts defined' do
|
@@ -226,17 +222,16 @@ describe Praxis::Types::MultipartArray do
|
|
226
222
|
subject(:dumped) { payload.dump }
|
227
223
|
|
228
224
|
it 'dumps' do
|
229
|
-
|
225
|
+
type.load(dumped, content_type: payload.content_type)
|
230
226
|
end
|
231
227
|
context 'an example' do
|
232
228
|
let(:payload) { type.example }
|
233
229
|
|
234
230
|
it 'dumps' do
|
235
|
-
|
231
|
+
type.load(dumped, content_type: payload.content_type)
|
236
232
|
end
|
237
233
|
end
|
238
234
|
|
239
|
-
|
240
235
|
context 'with default_format' do
|
241
236
|
let(:type) do
|
242
237
|
Class.new(Praxis::Types::MultipartArray) do
|
@@ -267,7 +262,7 @@ describe Praxis::Types::MultipartArray do
|
|
267
262
|
|
268
263
|
let(:output) { example.dump(default_format: default_format) }
|
269
264
|
|
270
|
-
let(:parts) { Praxis::MultipartParser.parse({'Content-Type'=>example.content_type}, output).last }
|
265
|
+
let(:parts) { Praxis::MultipartParser.parse({ 'Content-Type' => example.content_type }, output).last }
|
271
266
|
|
272
267
|
it 'dumps the parts with the proper handler' do
|
273
268
|
json_handler = Praxis::Application.instance.handlers['json']
|
@@ -290,9 +285,7 @@ describe Praxis::Types::MultipartArray do
|
|
290
285
|
expect(instance.payload).to eq json_handler.generate(example.part('instances')[i].payload.dump)
|
291
286
|
end
|
292
287
|
end
|
293
|
-
|
294
288
|
end
|
295
|
-
|
296
289
|
end
|
297
290
|
|
298
291
|
context 'with errors' do
|
@@ -300,11 +293,10 @@ describe Praxis::Types::MultipartArray do
|
|
300
293
|
form_data = MIME::Multipart::FormData.new
|
301
294
|
|
302
295
|
entity = MIME::Text.new('James')
|
303
|
-
form_data.add entity,'name'
|
304
|
-
|
296
|
+
form_data.add entity, 'name'
|
305
297
|
|
306
298
|
entity = MIME::Text.new('file1')
|
307
|
-
form_data.add entity,'files', 'file1'
|
299
|
+
form_data.add entity, 'files', 'file1'
|
308
300
|
|
309
301
|
form_data
|
310
302
|
end
|
@@ -314,10 +306,10 @@ describe Praxis::Types::MultipartArray do
|
|
314
306
|
it 'validates part headers' do
|
315
307
|
expect(errors).to have(3).items
|
316
308
|
expect(errors).to match_array([
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
309
|
+
/\.name\.payload value .* does not match regexp/,
|
310
|
+
/\.files\.headers.* is not within the allowed values/,
|
311
|
+
/\.title is required/
|
312
|
+
])
|
321
313
|
end
|
322
314
|
end
|
323
315
|
|
@@ -327,14 +319,14 @@ describe Praxis::Types::MultipartArray do
|
|
327
319
|
it 'generates parts' do
|
328
320
|
title = payload.part('title')
|
329
321
|
expect(title).to_not be_nil
|
330
|
-
expect(title.payload).to match
|
322
|
+
expect(title.payload).to match(/\w+/)
|
331
323
|
|
332
324
|
files = payload.part('files')
|
333
325
|
expect(files).to have(2).items
|
334
326
|
|
335
327
|
files.each do |file|
|
336
328
|
expect(file.payload).to be_kind_of(Tempfile)
|
337
|
-
expect(file.filename).to match
|
329
|
+
expect(file.filename).to match(/\w+/)
|
338
330
|
|
339
331
|
expect(file.headers['Content-Type']).to eq 'application/octet-stream'
|
340
332
|
end
|
@@ -343,15 +335,14 @@ describe Praxis::Types::MultipartArray do
|
|
343
335
|
it 'is valid' do
|
344
336
|
expect(payload.validate).to have(0).items
|
345
337
|
end
|
346
|
-
|
347
338
|
end
|
348
339
|
|
349
340
|
context 'with a hackish default part definition' do
|
350
341
|
let(:type) do
|
351
342
|
Class.new(Praxis::Types::MultipartArray) do
|
352
|
-
|
343
|
+
options[:case_insensitive_load] = true
|
353
344
|
|
354
|
-
part
|
345
|
+
part(/\d+/, Instance)
|
355
346
|
end
|
356
347
|
end
|
357
348
|
|
@@ -362,7 +353,7 @@ describe Praxis::Types::MultipartArray do
|
|
362
353
|
instance = Instance.example("instance-#{i}")
|
363
354
|
body = JSON.pretty_generate(instance.render)
|
364
355
|
entity = MIME::Text.new(body)
|
365
|
-
form_data.add entity,i.to_s
|
356
|
+
form_data.add entity, i.to_s
|
366
357
|
end
|
367
358
|
|
368
359
|
form_data
|
@@ -373,10 +364,8 @@ describe Praxis::Types::MultipartArray do
|
|
373
364
|
expect(part.payload).to be_kind_of(Instance)
|
374
365
|
end
|
375
366
|
end
|
376
|
-
|
377
367
|
end
|
378
368
|
|
379
|
-
|
380
369
|
context 'anonymous generation' do
|
381
370
|
let(:definition_block) do
|
382
371
|
proc do
|
@@ -396,7 +385,7 @@ describe Praxis::Types::MultipartArray do
|
|
396
385
|
instance = Instance.example("instance-#{i}")
|
397
386
|
body = JSON.pretty_generate(instance.render)
|
398
387
|
entity = MIME::Text.new(body)
|
399
|
-
form_data.add entity,i.to_s
|
388
|
+
form_data.add entity, i.to_s
|
400
389
|
end
|
401
390
|
|
402
391
|
form_data
|
@@ -411,9 +400,5 @@ describe Praxis::Types::MultipartArray do
|
|
411
400
|
expect(part.payload).to be_kind_of(Instance)
|
412
401
|
end
|
413
402
|
end
|
414
|
-
|
415
|
-
|
416
403
|
end
|
417
|
-
|
418
|
-
|
419
404
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Concerns
|
2
4
|
module Authenticated
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
include Praxis::Callbacks
|
5
|
-
|
7
|
+
|
6
8
|
included do
|
7
9
|
before :action do |controller|
|
8
10
|
auth_data = controller.request.headers['Authorization']
|
9
|
-
if auth_data && auth_data !~ /secret/
|
10
|
-
Praxis::Responses::Unauthorized.new(body: 'Authentication info is invalid')
|
11
|
-
end
|
11
|
+
Praxis::Responses::Unauthorized.new(body: 'Authentication info is invalid') if auth_data && auth_data !~ /secret/
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Concerns
|
2
4
|
module LogWrapper
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
include Praxis::Callbacks
|
5
|
-
|
7
|
+
|
6
8
|
included do
|
7
|
-
before :around do |
|
9
|
+
before :around do |_controller, callee|
|
8
10
|
# Log something at the beginning
|
9
11
|
callee.call
|
10
12
|
# Log something at the end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end
|