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.
- 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,17 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::ApiDefinition do
|
|
4
|
-
|
|
5
|
-
subject(:api){ Praxis::ApiDefinition.instance }
|
|
6
|
+
subject(:api) { Praxis::ApiDefinition.instance }
|
|
6
7
|
|
|
7
8
|
# Without getting a fresh new ApiDefinition it is very difficult to test stuff using the Singleton
|
|
8
9
|
# So for some tests we're gonna create a new instance and work with it to avoid the singleton issues
|
|
9
10
|
let(:non_singleton_api) do
|
|
10
|
-
api_def=Praxis::ApiDefinition.__send__(:new)
|
|
11
|
+
api_def = Praxis::ApiDefinition.__send__(:new)
|
|
11
12
|
api_def.instance_eval do |api|
|
|
12
|
-
api.response_template :template1, &
|
|
13
|
-
api.trait :trait1, &
|
|
14
|
-
api.trait :
|
|
13
|
+
api.response_template :template1, &proc {}
|
|
14
|
+
api.trait :trait1, &proc {}
|
|
15
|
+
api.trait :secondtrait do
|
|
15
16
|
description 'the second testing trait'
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -26,16 +27,16 @@ describe Praxis::ApiDefinition do
|
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
let(:info_block) do
|
|
29
|
-
|
|
30
|
-
name
|
|
31
|
-
title
|
|
30
|
+
proc do
|
|
31
|
+
name 'Name'
|
|
32
|
+
title 'Title'
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
context 'singleton' do
|
|
36
37
|
it 'should be a Singleton' do
|
|
37
|
-
expect(Praxis::ApiDefinition.ancestors).to include(
|
|
38
|
-
expect(subject).to eq(Praxis::ApiDefinition.instance
|
|
38
|
+
expect(Praxis::ApiDefinition.ancestors).to include(Singleton)
|
|
39
|
+
expect(subject).to eq(Praxis::ApiDefinition.instance)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
it 'has the :ok and :created response templates registered' do
|
|
@@ -44,10 +45,9 @@ describe Praxis::ApiDefinition do
|
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
|
|
48
48
|
context '.response_template' do
|
|
49
|
-
let(:response_template){
|
|
50
|
-
let(:api){ non_singleton_api }
|
|
49
|
+
let(:response_template) { proc {} }
|
|
50
|
+
let(:api) { non_singleton_api }
|
|
51
51
|
|
|
52
52
|
it 'has the defined template1 response_template' do
|
|
53
53
|
expect(api.responses.keys).to include(:template1)
|
|
@@ -61,7 +61,7 @@ describe Praxis::ApiDefinition do
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
context '.response' do
|
|
64
|
-
let(:api){ non_singleton_api }
|
|
64
|
+
let(:api) { non_singleton_api }
|
|
65
65
|
|
|
66
66
|
it 'returns a registered response by name' do
|
|
67
67
|
expect(api.response(:template1)).to be_kind_of(Praxis::ResponseTemplate)
|
|
@@ -69,9 +69,9 @@ describe Praxis::ApiDefinition do
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
context '.trait' do
|
|
72
|
-
let(:api){ non_singleton_api }
|
|
72
|
+
let(:api) { non_singleton_api }
|
|
73
73
|
|
|
74
|
-
let(:trait2){
|
|
74
|
+
let(:trait2) { proc {} }
|
|
75
75
|
|
|
76
76
|
it 'has the defined trait1 ' do
|
|
77
77
|
expect(api.traits.keys).to include(:trait1)
|
|
@@ -80,19 +80,18 @@ describe Praxis::ApiDefinition do
|
|
|
80
80
|
|
|
81
81
|
it 'complains trying to register traits with same name' do
|
|
82
82
|
api.trait :trait2, &trait2
|
|
83
|
-
expect
|
|
83
|
+
expect do
|
|
84
84
|
api.trait :trait2, &trait2
|
|
85
|
-
|
|
85
|
+
end.to raise_error(Praxis::Exceptions::InvalidTrait, /Overwriting a previous trait with the same name/)
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
context '.info' do
|
|
90
|
-
|
|
91
|
-
let(:api){ non_singleton_api }
|
|
90
|
+
let(:api) { non_singleton_api }
|
|
92
91
|
subject(:info) { api.info('1.0') }
|
|
93
92
|
|
|
94
93
|
context '.base_path' do
|
|
95
|
-
its(:base_path) { should eq '/apps/:app_name'}
|
|
94
|
+
its(:base_path) { should eq '/apps/:app_name' }
|
|
96
95
|
end
|
|
97
96
|
|
|
98
97
|
context '.base_params' do
|
|
@@ -103,9 +102,9 @@ describe Praxis::ApiDefinition do
|
|
|
103
102
|
|
|
104
103
|
context 'with a version' do
|
|
105
104
|
it 'saves the data into the correct version hash' do
|
|
106
|
-
expect(api.infos.keys).to_not include(
|
|
107
|
-
api.info(
|
|
108
|
-
expect(api.infos.keys).to include(
|
|
105
|
+
expect(api.infos.keys).to_not include('9.0')
|
|
106
|
+
api.info('9.0', &info_block)
|
|
107
|
+
expect(api.infos.keys).to include('9.0')
|
|
109
108
|
end
|
|
110
109
|
end
|
|
111
110
|
|
|
@@ -113,7 +112,7 @@ describe Praxis::ApiDefinition do
|
|
|
113
112
|
it 'saves it into global_info' do
|
|
114
113
|
expect(api.infos.keys).to_not include(nil)
|
|
115
114
|
api.info do
|
|
116
|
-
description
|
|
115
|
+
description 'Global Description'
|
|
117
116
|
end
|
|
118
117
|
expect(api.infos.keys).to_not include(nil)
|
|
119
118
|
expect(api.global_info.description).to eq 'Global Description'
|
|
@@ -122,10 +121,10 @@ describe Praxis::ApiDefinition do
|
|
|
122
121
|
end
|
|
123
122
|
|
|
124
123
|
context '.describe' do
|
|
125
|
-
subject(:output){ api.describe }
|
|
124
|
+
subject(:output) { api.describe }
|
|
126
125
|
|
|
127
126
|
context 'using the spec_app definitions' do
|
|
128
|
-
subject(:version_output){ output[
|
|
127
|
+
subject(:version_output) { output['1.0'][:info] }
|
|
129
128
|
|
|
130
129
|
context 'for the global_info data' do
|
|
131
130
|
subject(:info) { output[:global][:info] }
|
|
@@ -136,46 +135,45 @@ describe Praxis::ApiDefinition do
|
|
|
136
135
|
end
|
|
137
136
|
|
|
138
137
|
it 'outputs data for 1.0 info' do
|
|
139
|
-
expect(output.keys).to include(
|
|
140
|
-
expect(output[
|
|
138
|
+
expect(output.keys).to include('1.0')
|
|
139
|
+
expect(output['1.0']).to include(:info)
|
|
141
140
|
end
|
|
142
141
|
|
|
143
142
|
it 'describes 1.0 Api info properly' do
|
|
144
|
-
info = output[
|
|
143
|
+
info = output['1.0'][:info]
|
|
145
144
|
expect(info).to include(:schema_version, :name, :title, :description, :base_path)
|
|
146
|
-
expect(info[:schema_version]).to eq(
|
|
147
|
-
expect(info[:name]).to eq(
|
|
148
|
-
expect(info[:title]).to eq(
|
|
149
|
-
expect(info[:description]).to eq(
|
|
150
|
-
expect(info[:base_path]).to eq(
|
|
145
|
+
expect(info[:schema_version]).to eq('1.0')
|
|
146
|
+
expect(info[:name]).to eq('Spec App')
|
|
147
|
+
expect(info[:title]).to eq('A simple App to do some simple integration testing')
|
|
148
|
+
expect(info[:description]).to eq('A simple 1.0 App')
|
|
149
|
+
expect(info[:base_path]).to eq('/api')
|
|
151
150
|
end
|
|
152
151
|
end
|
|
153
152
|
|
|
154
153
|
context 'using a non-singleton object' do
|
|
155
|
-
let(:api){ non_singleton_api }
|
|
154
|
+
let(:api) { non_singleton_api }
|
|
156
155
|
|
|
157
156
|
before do
|
|
158
|
-
api.info(
|
|
157
|
+
api.info('9.0', &info_block)
|
|
159
158
|
api.info do
|
|
160
|
-
description
|
|
159
|
+
description 'Global Description'
|
|
161
160
|
end
|
|
162
161
|
end
|
|
163
|
-
its(:keys) { should include(
|
|
162
|
+
its(:keys) { should include('9.0') }
|
|
164
163
|
its(:keys) { should include :traits }
|
|
165
|
-
its([
|
|
164
|
+
its(%i[traits secondtrait]) { should eq api.traits[:secondtrait].describe }
|
|
166
165
|
|
|
167
166
|
context 'for v9.0 info' do
|
|
168
|
-
subject(:v9_info){ output[
|
|
167
|
+
subject(:v9_info) { output['9.0'][:info] }
|
|
169
168
|
|
|
170
169
|
it 'has the info it was set in the call' do
|
|
171
|
-
expect(v9_info).to include({schema_version:
|
|
172
|
-
expect(v9_info).to include({name:
|
|
173
|
-
expect(v9_info).to include({title:
|
|
170
|
+
expect(v9_info).to include({ schema_version: '1.0' })
|
|
171
|
+
expect(v9_info).to include({ name: 'Name' })
|
|
172
|
+
expect(v9_info).to include({ title: 'Title' })
|
|
174
173
|
end
|
|
175
174
|
it 'inherited the description from the nil(global) one' do
|
|
176
|
-
expect(v9_info).to include({description:
|
|
175
|
+
expect(v9_info).to include({ description: 'Global Description' })
|
|
177
176
|
end
|
|
178
|
-
|
|
179
177
|
end
|
|
180
178
|
end
|
|
181
179
|
end
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::ApiGeneralInfo do
|
|
4
|
-
|
|
5
|
-
subject(:info){ Praxis::ApiGeneralInfo.new }
|
|
6
|
+
subject(:info) { Praxis::ApiGeneralInfo.new }
|
|
6
7
|
|
|
7
8
|
before do
|
|
8
|
-
allow(Praxis::Application.instance).to receive(:versioning_scheme=).with([
|
|
9
|
+
allow(Praxis::Application.instance).to receive(:versioning_scheme=).with(%i[header params])
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
|
|
12
12
|
let(:info_block) do
|
|
13
|
-
|
|
14
|
-
name
|
|
15
|
-
title
|
|
16
|
-
description
|
|
13
|
+
proc do
|
|
14
|
+
name 'Name'
|
|
15
|
+
title 'Title'
|
|
16
|
+
description 'Description'
|
|
17
17
|
endpoint 'api.example.com'
|
|
18
|
-
base_path
|
|
18
|
+
base_path '/base'
|
|
19
19
|
|
|
20
20
|
consumes 'json'
|
|
21
21
|
produces 'json'
|
|
@@ -28,44 +28,44 @@ describe Praxis::ApiGeneralInfo do
|
|
|
28
28
|
|
|
29
29
|
context 'setting' do
|
|
30
30
|
it 'accepts the appropriate DSLs' do
|
|
31
|
-
expect
|
|
32
|
-
info.instance_exec
|
|
33
|
-
|
|
31
|
+
expect do
|
|
32
|
+
info.instance_exec(&info_block)
|
|
33
|
+
end.to_not raise_error
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
context 'getting values' do
|
|
38
38
|
before do
|
|
39
|
-
info.instance_exec
|
|
39
|
+
info.instance_exec(&info_block)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
its(:name) { should eq 'Name' }
|
|
43
|
-
its(:consumes) { should eq ['json']}
|
|
44
|
-
its(:produces) { should eq ['json']}
|
|
43
|
+
its(:consumes) { should eq ['json'] }
|
|
44
|
+
its(:produces) { should eq ['json'] }
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
context '.describe' do
|
|
48
48
|
before do
|
|
49
|
-
info.instance_exec
|
|
49
|
+
info.instance_exec(&info_block)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
subject(:output){ info.describe }
|
|
53
|
-
its([:schema_version]) {should eq '1.0' }
|
|
54
|
-
its([:name]) {should eq 'Name' }
|
|
55
|
-
its([:title]) {should eq 'Title' }
|
|
56
|
-
its([:description]) {should eq 'Description' }
|
|
57
|
-
its([:base_path]) {should eq '/base' }
|
|
52
|
+
subject(:output) { info.describe }
|
|
53
|
+
its([:schema_version]) { should eq '1.0' }
|
|
54
|
+
its([:name]) { should eq 'Name' }
|
|
55
|
+
its([:title]) { should eq 'Title' }
|
|
56
|
+
its([:description]) { should eq 'Description' }
|
|
57
|
+
its([:base_path]) { should eq '/base' }
|
|
58
58
|
its([:base_params]) { should have_key :name }
|
|
59
|
-
its([
|
|
60
|
-
its([:version_with]) { should eq([
|
|
59
|
+
its(%i[base_params name type name]) { should eq 'String' }
|
|
60
|
+
its([:version_with]) { should eq(%i[header params]) }
|
|
61
61
|
its([:endpoint]) { should eq 'api.example.com' }
|
|
62
62
|
its([:consumes]) { should eq ['json'] }
|
|
63
63
|
its([:produces]) { should eq ['json'] }
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
context 'base_path with versioning' do
|
|
67
|
-
let(:global_info){ Praxis::ApiGeneralInfo.new }
|
|
68
|
-
subject(:info){ Praxis::ApiGeneralInfo.new(global_info, version: '1.0') }
|
|
67
|
+
let(:global_info) { Praxis::ApiGeneralInfo.new }
|
|
68
|
+
subject(:info) { Praxis::ApiGeneralInfo.new(global_info, version: '1.0') }
|
|
69
69
|
|
|
70
70
|
before do
|
|
71
71
|
global_info
|
|
@@ -74,9 +74,8 @@ describe Praxis::ApiGeneralInfo do
|
|
|
74
74
|
|
|
75
75
|
global_info.version_with :path
|
|
76
76
|
global_info.base_path '/api/v:api_version'
|
|
77
|
-
end
|
|
77
|
+
end
|
|
78
78
|
|
|
79
|
-
its(:base_path) { should eq '/api/v1.0'}
|
|
79
|
+
its(:base_path) { should eq '/api/v1.0' }
|
|
80
80
|
end
|
|
81
|
-
|
|
82
81
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::Application do
|
|
@@ -6,29 +8,31 @@ describe Praxis::Application do
|
|
|
6
8
|
app = Class.new(Praxis::Application).instance
|
|
7
9
|
|
|
8
10
|
config = Object.new
|
|
9
|
-
def config.define(key=nil, type=Attributor::Struct, **opts, &block)
|
|
10
|
-
|
|
11
|
+
def config.define(key = nil, type = Attributor::Struct, **opts, &block)
|
|
12
|
+
[key, type, opts, block]
|
|
11
13
|
end
|
|
14
|
+
|
|
12
15
|
def config.get
|
|
13
|
-
|
|
16
|
+
'gotconfig'
|
|
14
17
|
end
|
|
18
|
+
|
|
15
19
|
def config.set(config)
|
|
16
|
-
|
|
20
|
+
config
|
|
17
21
|
end
|
|
18
22
|
app.instance_variable_set(:@config, config)
|
|
19
23
|
app
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
describe '#config' do
|
|
23
|
-
let(:myblock){
|
|
27
|
+
let(:myblock) { -> {} }
|
|
24
28
|
it 'passes the block to config (and sets the right defaults)' do
|
|
25
29
|
ret = app.config(&myblock)
|
|
26
|
-
expect(ret).to eq([nil,Attributor::Struct,{},myblock])
|
|
30
|
+
expect(ret).to eq([nil, Attributor::Struct, {}, myblock])
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
it 'passes the params and block to config' do
|
|
30
|
-
ret = app.config(:key, Attributor::Hash, **{option: :one}, &myblock)
|
|
31
|
-
expect(ret).to eq([:key, Attributor::Hash, {option: :one}, myblock])
|
|
34
|
+
ret = app.config(:key, Attributor::Hash, **{ option: :one }, &myblock)
|
|
35
|
+
expect(ret).to eq([:key, Attributor::Hash, { option: :one }, myblock])
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
it 'gets config with no block given' do
|
|
@@ -69,13 +73,13 @@ describe Praxis::Application do
|
|
|
69
73
|
|
|
70
74
|
context 'given a non-Class' do
|
|
71
75
|
it 'raises' do
|
|
72
|
-
expect
|
|
76
|
+
expect do
|
|
73
77
|
subject.handler('awesomesauce', 'hi') # no instances allowed
|
|
74
|
-
|
|
78
|
+
end.to raise_error(NoMethodError)
|
|
75
79
|
|
|
76
|
-
expect
|
|
80
|
+
expect do
|
|
77
81
|
subject.handler('awesomesauce', ::Kernel) # no modules allowed
|
|
78
|
-
|
|
82
|
+
end.to raise_error(NoMethodError)
|
|
79
83
|
end
|
|
80
84
|
end
|
|
81
85
|
|
|
@@ -86,9 +90,9 @@ describe Praxis::Application do
|
|
|
86
90
|
end
|
|
87
91
|
|
|
88
92
|
it 'ensures that handlers will work' do
|
|
89
|
-
expect
|
|
93
|
+
expect do
|
|
90
94
|
subject.handler new_handler_name, bad_handler_class
|
|
91
|
-
|
|
95
|
+
end.to raise_error(ArgumentError)
|
|
92
96
|
end
|
|
93
97
|
end
|
|
94
98
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
|
3
4
|
|
|
4
5
|
describe Praxis::Blueprint do
|
|
5
6
|
subject(:blueprint_class) { PersonBlueprint }
|
|
@@ -8,11 +9,11 @@ describe Praxis::Blueprint do
|
|
|
8
9
|
|
|
9
10
|
context 'deterministic examples' do
|
|
10
11
|
it 'works' do
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
person1 = PersonBlueprint.example('person 1')
|
|
13
|
+
person2 = PersonBlueprint.example('person 1')
|
|
13
14
|
|
|
14
|
-
expect(
|
|
15
|
-
expect(
|
|
15
|
+
expect(person1.name).to eq(person2.name)
|
|
16
|
+
expect(person1.address.name).to eq(person2.address.name)
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
@@ -21,10 +22,10 @@ describe Praxis::Blueprint do
|
|
|
21
22
|
|
|
22
23
|
it { should_not be(nil) }
|
|
23
24
|
it 'contains all attributes' do
|
|
24
|
-
simple_attributes = [
|
|
25
|
+
simple_attributes = %i[id name street state]
|
|
25
26
|
expect(default_fieldset.keys).to match_array(simple_attributes)
|
|
26
27
|
# Should not have blueprint-derived attributes (or collections of them)
|
|
27
|
-
expect(default_fieldset.keys).to_not include(
|
|
28
|
+
expect(default_fieldset.keys).to_not include(AddressBlueprint.attributes.keys - simple_attributes)
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
|
|
@@ -77,7 +78,6 @@ describe Praxis::Blueprint do
|
|
|
77
78
|
expect(blueprint_class.attribute.type).to be blueprint_class::Struct
|
|
78
79
|
end
|
|
79
80
|
|
|
80
|
-
|
|
81
81
|
context 'an instance' do
|
|
82
82
|
shared_examples 'a blueprint instance' do
|
|
83
83
|
let(:expected_name) { blueprint_instance.name }
|
|
@@ -99,13 +99,12 @@ describe Praxis::Blueprint do
|
|
|
99
99
|
|
|
100
100
|
context 'from Blueprint.example' do
|
|
101
101
|
subject(:blueprint_instance) do
|
|
102
|
-
blueprint_class.example('ExamplePersonBlueprint',
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
)
|
|
102
|
+
blueprint_class.example('ExamplePersonBlueprint',
|
|
103
|
+
address: nil,
|
|
104
|
+
prior_addresses: [],
|
|
105
|
+
work_address: nil,
|
|
106
|
+
myself: nil,
|
|
107
|
+
friends: [])
|
|
109
108
|
end
|
|
110
109
|
it_behaves_like 'a blueprint instance'
|
|
111
110
|
end
|
|
@@ -236,25 +235,25 @@ describe Praxis::Blueprint do
|
|
|
236
235
|
let(:person) { PersonBlueprint.example('1') }
|
|
237
236
|
it 'is an alias to dump' do
|
|
238
237
|
person.object.contents
|
|
239
|
-
rendered = PersonBlueprint.render(person, fields: [
|
|
240
|
-
dumped = PersonBlueprint.dump(person, fields: [
|
|
238
|
+
rendered = PersonBlueprint.render(person, fields: %i[name full_name])
|
|
239
|
+
dumped = PersonBlueprint.dump(person, fields: %i[name full_name])
|
|
241
240
|
expect(rendered).to eq(dumped)
|
|
242
241
|
end
|
|
243
242
|
end
|
|
244
243
|
|
|
245
244
|
context '#render' do
|
|
246
245
|
let(:person) { PersonBlueprint.example }
|
|
247
|
-
let(:fields) do
|
|
246
|
+
let(:fields) do
|
|
248
247
|
{
|
|
249
248
|
name: true,
|
|
250
249
|
full_name: true,
|
|
251
250
|
address: {
|
|
252
251
|
street: true,
|
|
253
|
-
state: true
|
|
252
|
+
state: true
|
|
254
253
|
},
|
|
255
254
|
prior_addresses: {
|
|
256
255
|
street: true,
|
|
257
|
-
state: true
|
|
256
|
+
state: true
|
|
258
257
|
}
|
|
259
258
|
}
|
|
260
259
|
end
|
|
@@ -262,15 +261,16 @@ describe Praxis::Blueprint do
|
|
|
262
261
|
subject(:output) { person.render(fields: fields, **render_opts) }
|
|
263
262
|
|
|
264
263
|
context 'without passing fields' do
|
|
265
|
-
it 'renders the default field set defined' do
|
|
266
|
-
rendered = person.render(
|
|
264
|
+
it 'renders the default field set defined' do
|
|
265
|
+
rendered = person.render(**render_opts)
|
|
267
266
|
default_top_fields = PersonBlueprint.default_fieldset.keys
|
|
268
267
|
expect(rendered.keys).to match_array(default_top_fields)
|
|
269
|
-
expect(default_top_fields).to match_array([
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
expect(default_top_fields).to match_array(%i[
|
|
269
|
+
name
|
|
270
|
+
full_name
|
|
271
|
+
address
|
|
272
|
+
prior_addresses
|
|
273
|
+
])
|
|
274
274
|
end
|
|
275
275
|
end
|
|
276
276
|
context 'with a sub-attribute that is a blueprint' do
|
|
@@ -317,17 +317,16 @@ describe Praxis::Blueprint do
|
|
|
317
317
|
end
|
|
318
318
|
|
|
319
319
|
context 'using un-expanded fields for blueprints' do
|
|
320
|
-
let(:fields) do
|
|
320
|
+
let(:fields) do
|
|
321
321
|
{
|
|
322
322
|
name: true,
|
|
323
|
-
address: true
|
|
323
|
+
address: true # A blueprint!
|
|
324
324
|
}
|
|
325
325
|
end
|
|
326
326
|
it 'should still render the blueprint sub-attribute with its default fieldset' do
|
|
327
327
|
address_default_top_fieldset = AddressBlueprint.default_fieldset.keys
|
|
328
328
|
expect(output[:address].keys).to match(address_default_top_fieldset)
|
|
329
329
|
end
|
|
330
|
-
|
|
331
330
|
end
|
|
332
331
|
end
|
|
333
332
|
|
|
@@ -346,7 +345,7 @@ describe Praxis::Blueprint do
|
|
|
346
345
|
|
|
347
346
|
context 'FieldsetParser' do
|
|
348
347
|
let(:definition_block) do
|
|
349
|
-
|
|
348
|
+
proc do
|
|
350
349
|
attribute :one
|
|
351
350
|
attribute :two do
|
|
352
351
|
attribute :sub_two
|
|
@@ -356,17 +355,17 @@ describe Praxis::Blueprint do
|
|
|
356
355
|
subject { described_class::FieldsetParser.new(&definition_block) }
|
|
357
356
|
|
|
358
357
|
it 'parses properly' do
|
|
359
|
-
expect(subject.fieldset).to eq(one: true, two: { sub_two: true}
|
|
358
|
+
expect(subject.fieldset).to eq(one: true, two: { sub_two: true })
|
|
360
359
|
end
|
|
361
360
|
|
|
362
361
|
context 'with attribute parameters' do
|
|
363
362
|
let(:definition_block) do
|
|
364
|
-
|
|
363
|
+
proc do
|
|
365
364
|
attribute :one, view: :other
|
|
366
365
|
end
|
|
367
366
|
end
|
|
368
367
|
it 'complains and gives instructions if legacy view :default' do
|
|
369
|
-
expect{ subject.fieldset }.to raise_error(/Default fieldset definitions do not accept parameters/)
|
|
368
|
+
expect { subject.fieldset }.to raise_error(/Default fieldset definitions do not accept parameters/)
|
|
370
369
|
end
|
|
371
370
|
end
|
|
372
371
|
end
|