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,49 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'spec_helper'
|
|
3
4
|
|
|
4
5
|
describe Praxis::Mapper::SelectorGenerator do
|
|
5
6
|
let(:resource) { SimpleResource }
|
|
6
|
-
subject(:generator) {described_class.new }
|
|
7
|
+
subject(:generator) { described_class.new }
|
|
7
8
|
|
|
8
9
|
context '#add' do
|
|
9
10
|
let(:resource) { SimpleResource }
|
|
10
11
|
shared_examples 'a proper selector' do
|
|
11
12
|
it { expect(generator.add(resource, fields).selectors.dump).to be_deep_equal selectors }
|
|
12
13
|
end
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
context 'basic combos' do
|
|
15
16
|
context 'direct column fields' do
|
|
16
|
-
let(:fields) { {id: true, foobar: true} }
|
|
17
|
-
let(:selectors) do
|
|
17
|
+
let(:fields) { { id: true, foobar: true } }
|
|
18
|
+
let(:selectors) do
|
|
18
19
|
{
|
|
19
20
|
model: SimpleModel,
|
|
20
|
-
columns: [
|
|
21
|
-
}
|
|
21
|
+
columns: %i[id foobar]
|
|
22
|
+
}
|
|
22
23
|
end
|
|
23
24
|
it_behaves_like 'a proper selector'
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
context 'aliased column fields' do
|
|
27
|
-
let(:fields) { {id: true, name: true} }
|
|
28
|
+
let(:fields) { { id: true, name: true } }
|
|
28
29
|
let(:selectors) do
|
|
29
30
|
{
|
|
30
31
|
model: SimpleModel,
|
|
31
|
-
columns: [
|
|
32
|
+
columns: %i[id simple_name]
|
|
32
33
|
}
|
|
33
34
|
end
|
|
34
35
|
it_behaves_like 'a proper selector'
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
context 'pure associations without recursion' do
|
|
38
|
-
let(:fields) { {other_model: true} }
|
|
39
|
+
let(:fields) { { other_model: true } }
|
|
39
40
|
let(:selectors) do
|
|
40
41
|
{
|
|
41
42
|
model: SimpleModel,
|
|
42
43
|
columns: [:other_model_id], # FK of the other_model association
|
|
43
44
|
tracks: {
|
|
44
|
-
other_model: {
|
|
45
|
+
other_model: {
|
|
45
46
|
columns: [:id], # joining key for the association
|
|
46
|
-
model: OtherModel
|
|
47
|
+
model: OtherModel
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
}
|
|
@@ -52,15 +53,15 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
context 'aliased associations without recursion' do
|
|
55
|
-
let(:fields) { {other_resource: true} }
|
|
56
|
+
let(:fields) { { other_resource: true } }
|
|
56
57
|
let(:selectors) do
|
|
57
58
|
{
|
|
58
59
|
model: SimpleModel,
|
|
59
60
|
columns: [:other_model_id], # FK of the other_model association
|
|
60
61
|
tracks: {
|
|
61
|
-
other_model: {
|
|
62
|
+
other_model: {
|
|
62
63
|
columns: [:id], # joining key for the association
|
|
63
|
-
model: OtherModel
|
|
64
|
+
model: OtherModel
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -68,15 +69,15 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
68
69
|
it_behaves_like 'a proper selector'
|
|
69
70
|
end
|
|
70
71
|
context 'aliased associations without recursion (that map to columns and other associations)' do
|
|
71
|
-
let(:fields) { {aliased_method: true} }
|
|
72
|
+
let(:fields) { { aliased_method: true } }
|
|
72
73
|
let(:selectors) do
|
|
73
74
|
{
|
|
74
75
|
model: SimpleModel,
|
|
75
|
-
columns: [
|
|
76
|
+
columns: %i[column1 other_model_id], # other_model_id => because of the association
|
|
76
77
|
tracks: {
|
|
77
|
-
other_model: {
|
|
78
|
+
other_model: {
|
|
78
79
|
columns: [:id], # joining key for the association
|
|
79
|
-
model: OtherModel
|
|
80
|
+
model: OtherModel
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
}
|
|
@@ -85,13 +86,13 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
85
86
|
end
|
|
86
87
|
|
|
87
88
|
context 'redefined associations that add some extra columns (would need both the underlying association AND the columns in place)' do
|
|
88
|
-
let(:fields) { {parent: true} }
|
|
89
|
+
let(:fields) { { parent: true } }
|
|
89
90
|
let(:selectors) do
|
|
90
91
|
{
|
|
91
92
|
model: SimpleModel,
|
|
92
|
-
columns: [
|
|
93
|
+
columns: %i[parent_id added_column],
|
|
93
94
|
tracks: {
|
|
94
|
-
parent: {
|
|
95
|
+
parent: {
|
|
95
96
|
columns: [:id],
|
|
96
97
|
model: ParentModel
|
|
97
98
|
}
|
|
@@ -102,29 +103,29 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
102
103
|
end
|
|
103
104
|
|
|
104
105
|
context 'a simple property that requires all fields' do
|
|
105
|
-
let(:fields) { {everything: true} }
|
|
106
|
+
let(:fields) { { everything: true } }
|
|
106
107
|
let(:selectors) do
|
|
107
108
|
{
|
|
108
109
|
model: SimpleModel,
|
|
109
|
-
columns: [:*]
|
|
110
|
+
columns: [:*]
|
|
110
111
|
}
|
|
111
112
|
end
|
|
112
113
|
it_behaves_like 'a proper selector'
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
context 'a simple property that requires itself' do
|
|
116
|
-
let(:fields) { {circular_dep: true} }
|
|
117
|
+
let(:fields) { { circular_dep: true } }
|
|
117
118
|
let(:selectors) do
|
|
118
119
|
{
|
|
119
120
|
model: SimpleModel,
|
|
120
|
-
columns: [
|
|
121
|
+
columns: %i[circular_dep column1] # allows to "expand" the dependency into itself + others
|
|
121
122
|
}
|
|
122
123
|
end
|
|
123
124
|
it_behaves_like 'a proper selector'
|
|
124
125
|
end
|
|
125
126
|
|
|
126
127
|
context 'a simple property without dependencies' do
|
|
127
|
-
let(:fields) { {no_deps: true} }
|
|
128
|
+
let(:fields) { { no_deps: true } }
|
|
128
129
|
let(:selectors) do
|
|
129
130
|
{
|
|
130
131
|
model: SimpleModel
|
|
@@ -132,13 +133,12 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
132
133
|
end
|
|
133
134
|
it_behaves_like 'a proper selector'
|
|
134
135
|
end
|
|
135
|
-
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
context 'nested tracking' do
|
|
139
139
|
context 'pure associations follow the nested fields' do
|
|
140
140
|
let(:fields) do
|
|
141
|
-
{
|
|
141
|
+
{
|
|
142
142
|
other_model: {
|
|
143
143
|
id: true
|
|
144
144
|
}
|
|
@@ -196,7 +196,7 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
196
196
|
let(:selectors) do
|
|
197
197
|
{
|
|
198
198
|
model: SimpleModel,
|
|
199
|
-
columns: [
|
|
199
|
+
columns: %i[parent_id added_column],
|
|
200
200
|
tracks: {
|
|
201
201
|
parent: {
|
|
202
202
|
model: ParentModel,
|
|
@@ -225,7 +225,7 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
225
225
|
tracks: {
|
|
226
226
|
other_model: {
|
|
227
227
|
model: OtherModel,
|
|
228
|
-
columns: [
|
|
228
|
+
columns: %i[id name]
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
}
|
|
@@ -242,7 +242,7 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
242
242
|
tracks: {
|
|
243
243
|
other_model: {
|
|
244
244
|
model: OtherModel,
|
|
245
|
-
columns: [
|
|
245
|
+
columns: %i[id name]
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
}
|
|
@@ -251,13 +251,13 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
251
251
|
end
|
|
252
252
|
|
|
253
253
|
context 'for a property that requires all fields from an association' do
|
|
254
|
-
let(:fields) { {everything_from_parent: true} }
|
|
254
|
+
let(:fields) { { everything_from_parent: true } }
|
|
255
255
|
let(:selectors) do
|
|
256
256
|
{
|
|
257
257
|
model: SimpleModel,
|
|
258
258
|
columns: [:parent_id],
|
|
259
259
|
tracks: {
|
|
260
|
-
parent: {
|
|
260
|
+
parent: {
|
|
261
261
|
model: ParentModel,
|
|
262
262
|
columns: [:*]
|
|
263
263
|
}
|
|
@@ -270,15 +270,15 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
270
270
|
|
|
271
271
|
context 'required extra select fields due to associations' do
|
|
272
272
|
context 'many_to_one' do
|
|
273
|
-
let(:fields) { {other_model: true} }
|
|
273
|
+
let(:fields) { { other_model: true } }
|
|
274
274
|
let(:selectors) do
|
|
275
275
|
{
|
|
276
276
|
model: SimpleModel,
|
|
277
277
|
columns: [:other_model_id], # FK of the other_model association
|
|
278
278
|
tracks: {
|
|
279
|
-
other_model: {
|
|
279
|
+
other_model: {
|
|
280
280
|
columns: [:id],
|
|
281
|
-
model: OtherModel
|
|
281
|
+
model: OtherModel
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
}
|
|
@@ -287,39 +287,73 @@ describe Praxis::Mapper::SelectorGenerator do
|
|
|
287
287
|
end
|
|
288
288
|
context 'one_to_many' do
|
|
289
289
|
let(:resource) { ParentResource }
|
|
290
|
-
let(:fields) { {simple_children: true} }
|
|
290
|
+
let(:fields) { { simple_children: true } }
|
|
291
291
|
let(:selectors) do
|
|
292
292
|
{
|
|
293
293
|
model: ParentModel,
|
|
294
294
|
columns: [:id], # No FKs in the source model for one_to_many
|
|
295
295
|
tracks: {
|
|
296
|
-
simple_children: {
|
|
296
|
+
simple_children: {
|
|
297
297
|
columns: [:parent_id],
|
|
298
|
-
model: SimpleModel
|
|
298
|
+
model: SimpleModel
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
end
|
|
303
303
|
it_behaves_like 'a proper selector'
|
|
304
|
-
end
|
|
304
|
+
end
|
|
305
305
|
context 'many_to_many' do
|
|
306
306
|
let(:resource) { OtherResource }
|
|
307
|
-
let(:fields) { {simple_models: true} }
|
|
307
|
+
let(:fields) { { simple_models: true } }
|
|
308
308
|
let(:selectors) do
|
|
309
309
|
{
|
|
310
310
|
model: OtherModel,
|
|
311
|
-
columns: [:id], #join key in the source model for many_to_many (where the middle table points to)
|
|
311
|
+
columns: [:id], # join key in the source model for many_to_many (where the middle table points to)
|
|
312
312
|
tracks: {
|
|
313
|
-
simple_models: {
|
|
314
|
-
columns: [:id], #join key in the target model for many_to_many (where the middle table points to)
|
|
313
|
+
simple_models: {
|
|
314
|
+
columns: [:id], # join key in the target model for many_to_many (where the middle table points to)
|
|
315
315
|
model: SimpleModel
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
end
|
|
320
320
|
it_behaves_like 'a proper selector'
|
|
321
|
-
end
|
|
321
|
+
end
|
|
322
322
|
|
|
323
|
+
context 'that are several attriutes deep' do
|
|
324
|
+
let(:fields) { { deep_nested_deps: true } }
|
|
325
|
+
let(:selectors) do
|
|
326
|
+
{
|
|
327
|
+
model: SimpleModel,
|
|
328
|
+
columns: [:parent_id],
|
|
329
|
+
tracks: {
|
|
330
|
+
parent: {
|
|
331
|
+
model: ParentModel,
|
|
332
|
+
columns: [:id], # No FKs in the source model for one_to_many
|
|
333
|
+
tracks: {
|
|
334
|
+
simple_children: {
|
|
335
|
+
columns: %i[parent_id other_model_id],
|
|
336
|
+
model: SimpleModel,
|
|
337
|
+
tracks: {
|
|
338
|
+
other_model: {
|
|
339
|
+
model: OtherModel,
|
|
340
|
+
columns: %i[id parent_id],
|
|
341
|
+
tracks: {
|
|
342
|
+
parent: {
|
|
343
|
+
model: ParentModel,
|
|
344
|
+
columns: %i[id simple_name other_attribute]
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
end
|
|
355
|
+
it_behaves_like 'a proper selector'
|
|
356
|
+
end
|
|
323
357
|
end
|
|
324
358
|
end
|
|
325
359
|
end
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Style/StringConcatenation
|
|
4
|
+
|
|
5
|
+
require 'spec_helper'
|
|
2
6
|
|
|
3
7
|
describe Praxis::MediaTypeIdentifier do
|
|
4
8
|
let(:example) { 'application/ice-cream+sundae; nuts="true"; fudge="true"' }
|
|
@@ -14,7 +18,7 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
context 'of empty string values' do
|
|
17
|
-
let(:example) {
|
|
21
|
+
let(:example) { '' }
|
|
18
22
|
it 'returns nil' do
|
|
19
23
|
expect(subject).to be(nil)
|
|
20
24
|
end
|
|
@@ -47,8 +51,6 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
47
51
|
# pending("need to stop using a regexp to do a context-free parser's job")
|
|
48
52
|
# expect(described_class.new(tricky_example).parameters['sauce']).to eq('yes; absolutely')
|
|
49
53
|
# end
|
|
50
|
-
|
|
51
|
-
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
context 'given a malformed type' do
|
|
@@ -164,7 +166,7 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
164
166
|
|
|
165
167
|
let(:with_suffix) { 'application/vnd.widget+xml' }
|
|
166
168
|
let(:with_subtype) { 'text/xml' }
|
|
167
|
-
let(:with_both) { 'text/json+xml' } #nonsensical but valid!
|
|
169
|
+
let(:with_both) { 'text/json+xml' } # nonsensical but valid!
|
|
168
170
|
|
|
169
171
|
it 'uses the suffix' do
|
|
170
172
|
expect(subject.new(with_suffix).handler_name).to eq('xml')
|
|
@@ -192,15 +194,15 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
192
194
|
|
|
193
195
|
it 'adds parameters' do
|
|
194
196
|
expect(simple_subject + 'nuts=true').to \
|
|
195
|
-
|
|
197
|
+
eq(described_class.new('application/vnd.icecream; nuts=true'))
|
|
196
198
|
|
|
197
199
|
expect(simple_subject + '; nuts=true').to \
|
|
198
|
-
|
|
200
|
+
eq(described_class.new('application/vnd.icecream; nuts=true'))
|
|
199
201
|
end
|
|
200
202
|
|
|
201
203
|
it 'adds suffix and parameters' do
|
|
202
204
|
expect(simple_subject + 'xml; nuts=true').to \
|
|
203
|
-
|
|
205
|
+
eq(described_class.new('application/vnd.icecream+xml; nuts=true'))
|
|
204
206
|
end
|
|
205
207
|
|
|
206
208
|
it 'replaces the suffix' do
|
|
@@ -210,7 +212,7 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
210
212
|
|
|
211
213
|
it 'replaces existing parameters and adds new ones' do
|
|
212
214
|
expect(complex_subject + 'nuts=false; cherry=true').to \
|
|
213
|
-
|
|
215
|
+
eq(described_class.new('application/vnd.icecream+json; cherry=true; nuts=false'))
|
|
214
216
|
|
|
215
217
|
expect(complex_subject + '; nuts=false; cherry=true').to \
|
|
216
218
|
eq(described_class.new('application/vnd.icecream+json; cherry=true; nuts=false'))
|
|
@@ -235,4 +237,5 @@ describe Praxis::MediaTypeIdentifier do
|
|
|
235
237
|
end
|
|
236
238
|
end
|
|
237
239
|
end
|
|
238
|
-
end
|
|
240
|
+
end
|
|
241
|
+
# rubocop:enable Style/StringConcatenation
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::MediaType do
|
|
@@ -5,19 +7,18 @@ describe Praxis::MediaType do
|
|
|
5
7
|
let(:manager_resource) { instance_double(Person, id: 101, name: /[:name:]/.gen, href: '/') }
|
|
6
8
|
let(:custodian_resource) { instance_double(Person, id: 102, name: /[:name:]/.gen, href: '/') }
|
|
7
9
|
let(:residents_summary_resource) do
|
|
8
|
-
instance_double(Person::CollectionSummary, href:
|
|
10
|
+
instance_double(Person::CollectionSummary, href: '/people', size: 2)
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
let(:resource) do
|
|
12
14
|
double('address',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
15
|
+
id: 1,
|
|
16
|
+
name: 'Home',
|
|
17
|
+
owner: owner_resource,
|
|
18
|
+
manager: manager_resource,
|
|
19
|
+
custodian: custodian_resource,
|
|
20
|
+
residents_summary: residents_summary_resource,
|
|
21
|
+
fields: { id: true, name: true })
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
subject(:address) { Address.new(resource) }
|
|
@@ -28,7 +29,6 @@ describe Praxis::MediaType do
|
|
|
28
29
|
its(:owner) { should be_instance_of(Person) }
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
|
|
32
32
|
context 'accessor methods' do
|
|
33
33
|
subject(:address_klass) { address.class }
|
|
34
34
|
|
|
@@ -41,12 +41,12 @@ describe Praxis::MediaType do
|
|
|
41
41
|
its(:description) { should be_kind_of(String) }
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
context
|
|
44
|
+
context 'rendering' do
|
|
45
45
|
subject(:output) { address.render }
|
|
46
46
|
|
|
47
47
|
its([:id]) { should eq(address.id) }
|
|
48
48
|
its([:name]) { should eq(address.name) }
|
|
49
49
|
its([:owner]) { should eq(Person.dump(owner_resource)) }
|
|
50
|
-
its([:fields]) { should eq(address.fields.dump
|
|
50
|
+
its([:fields]) { should eq(address.fields.dump) }
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -1,73 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::MiddlewareApp do
|
|
4
|
-
|
|
5
|
-
let(:
|
|
6
|
-
let(:
|
|
7
|
-
let(:instance){ middleware.new(target)}
|
|
6
|
+
let(:init_args) { { root: 'here' } }
|
|
7
|
+
let(:middleware) { Praxis::MiddlewareApp.for(**init_args) }
|
|
8
|
+
let(:instance) { middleware.new(target) }
|
|
8
9
|
|
|
9
10
|
context '.for' do
|
|
10
11
|
it 'does not initialize the Application instance yet' do
|
|
11
|
-
expect(
|
|
12
|
+
expect(Praxis::Application.instance).to_not receive(:setup)
|
|
12
13
|
middleware
|
|
13
14
|
end
|
|
14
15
|
it 'returns its class' do
|
|
15
|
-
expect(
|
|
16
|
+
expect(middleware).to be < Praxis::MiddlewareApp
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
context 'instantiated' do
|
|
20
|
-
subject{ instance }
|
|
21
|
-
let(:target_response){ [201,{}] }
|
|
22
|
-
let(:target){ double(
|
|
21
|
+
subject { instance }
|
|
22
|
+
let(:target_response) { [201, {}] }
|
|
23
|
+
let(:target) { double('target app', call: target_response) }
|
|
23
24
|
it 'saves the target app' do
|
|
24
25
|
expect(subject.target).to be(target)
|
|
25
26
|
end
|
|
26
27
|
it 'does not initialize the Application instance yet' do
|
|
27
|
-
expect(
|
|
28
|
+
expect(Praxis::Application.instance).to_not receive(:setup)
|
|
28
29
|
subject
|
|
29
30
|
end
|
|
30
|
-
|
|
31
|
+
|
|
31
32
|
context '.call' do
|
|
32
|
-
let(:env){ {} }
|
|
33
|
-
let(:praxis_response){ [200,{}] }
|
|
34
|
-
subject(:response){ instance.call(env) }
|
|
33
|
+
let(:env) { {} }
|
|
34
|
+
let(:praxis_response) { [200, {}] }
|
|
35
|
+
subject(:response) { instance.call(env) }
|
|
35
36
|
before do
|
|
36
37
|
# always invokes the praxis app
|
|
37
|
-
expect(
|
|
38
|
+
expect(Praxis::Application.instance).to receive(:call).with(env).once.and_return(praxis_response)
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
context 'when it has not been setup yet' do
|
|
41
42
|
it 'initializes the application singleton with the passed parameters' do
|
|
42
|
-
expect(
|
|
43
|
+
expect(Praxis::Application.instance).to receive(:setup).with(init_args).once
|
|
43
44
|
subject
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
context 'when it has already been setup' do
|
|
47
48
|
it 'does NOT call instance setup' do
|
|
48
49
|
middleware.setup
|
|
49
|
-
expect(
|
|
50
|
+
expect(Praxis::Application.instance).to_not receive(:setup)
|
|
50
51
|
subject
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
context 'properly handled (non-404 and 405) responses from praxis' do
|
|
55
56
|
it 'are returned straight through' do
|
|
56
|
-
expect(
|
|
57
|
+
expect(response).to be(praxis_response)
|
|
57
58
|
end
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
context '404/405 responses with X-Cascade = pass' do
|
|
61
|
-
let(:praxis_response){ [404, {'X-Cascade' => 'pass'}]}
|
|
62
|
+
let(:praxis_response) { [404, { 'X-Cascade' => 'pass' }] }
|
|
62
63
|
it 'are forwarded to the target app' do
|
|
63
|
-
expect(
|
|
64
|
+
expect(response).to be(target_response)
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
context '404/405 responses without X-Cascade = pass' do
|
|
68
|
-
let(:praxis_response){ [404, {}]}
|
|
69
|
+
let(:praxis_response) { [404, {}] }
|
|
69
70
|
it 'returned straight through' do
|
|
70
|
-
expect(
|
|
71
|
+
expect(response).to be(praxis_response)
|
|
71
72
|
end
|
|
72
73
|
end
|
|
73
74
|
end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::MultipartParser do
|
|
4
|
-
|
|
5
6
|
let(:form) do
|
|
6
7
|
form_data = MIME::Multipart::FormData.new
|
|
7
8
|
|
|
@@ -36,17 +37,16 @@ describe Praxis::MultipartParser do
|
|
|
36
37
|
form.add text, 'file', 'docker'
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
subject(:part) { parts.find { |p| p.name == 'file'} }
|
|
40
|
-
#subject(:part_body) { part.body }
|
|
41
|
-
|
|
40
|
+
subject(:part) { parts.find { |p| p.name == 'file' } }
|
|
41
|
+
# subject(:part_body) { part.body }
|
|
42
42
|
|
|
43
43
|
its(:payload) { should be_kind_of(Tempfile) }
|
|
44
|
-
its(:filename) { should eq(
|
|
45
|
-
its(:name) { should eq(
|
|
44
|
+
its(:filename) { should eq('docker') }
|
|
45
|
+
its(:name) { should eq('file') }
|
|
46
46
|
|
|
47
47
|
context 'headers' do
|
|
48
48
|
subject(:part_headers) { part.headers }
|
|
49
|
-
its(['Content-Type']) { should eq(
|
|
49
|
+
its(['Content-Type']) { should eq('text/plain') }
|
|
50
50
|
its(['Content-Disposition']) { should match(/filename=docker/) }
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -56,7 +56,5 @@ describe Praxis::MultipartParser do
|
|
|
56
56
|
part.payload.rewind
|
|
57
57
|
expect(part.payload.read).to eq('DOCKER_HOST=tcp://127.0.0.1:2375')
|
|
58
58
|
end
|
|
59
|
-
|
|
60
59
|
end
|
|
61
|
-
|
|
62
60
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::Notifications do
|
|
4
|
-
|
|
5
6
|
let(:events) { [] }
|
|
6
7
|
|
|
7
8
|
before do
|
|
8
|
-
Praxis::Notifications.subscribe('render') do |
|
|
9
|
+
Praxis::Notifications.subscribe('render') do |_name, _start, _finish, _id, payload|
|
|
9
10
|
events << payload
|
|
10
11
|
end
|
|
11
12
|
|
|
@@ -17,7 +18,6 @@ describe Praxis::Notifications do
|
|
|
17
18
|
|
|
18
19
|
it 'works' do
|
|
19
20
|
expect(events).to have(2).items
|
|
20
|
-
expect(events).to match [{extra: :information}, {extra: :single}]
|
|
21
|
+
expect(events).to match [{ extra: :information }, { extra: :single }]
|
|
21
22
|
end
|
|
22
|
-
|
|
23
23
|
end
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
5
|
describe Praxis::PluginConcern do
|
|
4
|
-
|
|
5
6
|
it 'works' do
|
|
6
7
|
expect(Praxis::Request.instance_methods).to include(:user_abilities)
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
context 'ActionDefinition' do
|
|
10
11
|
subject(:action) { ApiResources::Instances.actions[:terminate] }
|
|
11
|
-
its(:required_abilities) { should match_array [
|
|
12
|
+
its(:required_abilities) { should match_array %i[terminate read] }
|
|
12
13
|
|
|
13
14
|
context '#describe' do
|
|
14
15
|
subject(:describe) { action.describe }
|
|
15
|
-
it { should have_key :required_abilities}
|
|
16
|
-
its([:required_abilities]) { should match_array action.required_abilities}
|
|
16
|
+
it { should have_key :required_abilities }
|
|
17
|
+
its([:required_abilities]) { should match_array action.required_abilities }
|
|
17
18
|
end
|
|
18
|
-
|
|
19
19
|
end
|
|
20
|
-
|
|
21
20
|
end
|